Python 面向对象(笔记)

本文介绍了Python中的对象概念、类的定义与使用、成员方法、构造方法、私有成员、继承机制、多态性以及类型注解的使用,包括抽象类的设计和多态的应用,全面展示了面向对象编程的核心要素。
摘要由CSDN通过智能技术生成

一、初识对象

对象是类的实例化,是类的具体表现。对象包含了类定义的属性和方法,并且可以根据需要修改或调用。

二、成员方法

1、类的定义和使用

class 类名称:

        类的属性

        类的行为

· class是关键字,表示定义类

· 类的属性,既定义在类中的变量(成员变量)

· 类的行为,既定义在类中的函数(成员方法)

创建类对象的语法:

对象 = 类名称()

2、成员方法的定义语法

def 方法名(self,形参1,形参2,......,形参n):

        方法体

定义方法的参数列表中,有一个关键字:self。

self关键字必须存在:

· 表示类对象自身的意思

· 当我们使用类对象调用方法时,self会自动被python传入

· 在方法内部,想要访问类的成员变量,必须使用self

注意事项

self关键字,尽管在参数列表中,但是传参的时候可以忽略它。

# 设计一个类
class Student:
    name = None
    age = None
    def say_hi(self,msg):  # 类内部的函数叫方法
        print(f"大家好,我叫{self.name},{msg}")
    def say_hello(self):
        print("Hello")

# 创建一个学生对象
stu1 = Student()
stu1.name = "张三"
stu1.age = 18
stu1.say_hello()    # 调用时无需传参
stu1.say_hi("很高兴认识大家")      # 调用时,需要传msg参数

三、类和对象

1、使用类描述现实世界事物

现实世界的事物由属性和行为组成,类也可以包含属性和行为,所有用类描述现实世界事物非常合适。

2、类和对象的关系

类:相当于设计图纸

对象:相当于生产实体

类只是一种程序内的“设计图纸”,需要基于图纸生成实体(对象),才能正常工作。这种套路,称之为:“面向对象编程”

3、什么是面向对象

使用对象进行编程。设计一个类,基于类去创建一个对象,并使用对象来完成具体的工作。

 四、构造方法

属性(成员变量)的赋值

python类可以使用:__init__()方法,称之为构造方法。可以实现:

· 在创建类对象(构造类)的时候,会自动执行

· 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print(f"Student类创建了一个对象,{self.name},{self.age}")

stu1 = Student("张三", 18)

注意事项:

· 构造方法也是成员方法,不要忘记在参数列表中提供:self

· 在构造方法内定义成员变量,需要使用self关键字

五、其他内置方法

上述所学习的__init__构造方法,是python内置方法之一。

这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法

· __init__   ——构造方法

· __str__    ——字符串方法

· __It__      ——小于、大于符号比较

· __le__     ——小于等于、大于等于符号比较

· __eq__   —— ==符号比较

1、 __str__    ——字符串方法

当类对象需要被转换为字符串是,会输出如下结果(内存地址)

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

stu1 = Student("张三", 18)
print(stu1)
print(str(stu1))

运行结果为:

<__main__.Student object at 0x0000020374148760>
<__main__.Student object at 0x0000020374148760>

由于内存地址没有多大用途,故我们可以使用__str__方法,控制类转换为字符串的行为。

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"学生姓名:{self.name},年龄:{self.age}"

stu1 = Student("张三", 18)
print(stu1)
print(str(stu1))

运行结果:

学生姓名:张三,年龄:18
学生姓名:张三,年龄:18

2、__It__      ——小于、大于符号比较

直接两个对象进行比较时不可以的,但是在类中使用__lt__方法,可以同时完成:小于符号和大于符号的比较

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __lt__(self,other):
        return self.age < other.age

stu1 = Student("张三", 18)
stu2 = Student("李四", 20)
print(stu1 < stu2)
print(stu1 > stu2)

方法名: __lt__

传入参数:other,另一个类对象

返回值:True或False

内容:自行定义

3、 __le__     —— <=、>=符号比较

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __le__(self,other):
        return self.age <= other.age

4、  __eq__   —— ==符号比较

如果类中为定义__eq__方法,直接比较stu1和stu2类,默认比较这两个类的内存地址。结果返回为false。

定义__eq__方法,可以在方法内,定义比较哪个属性。

六、封装

1、私有成员

· 不公开的属性和行为,私有方法无法直接被类对象使用,私有变量无法被类对象赋值,也无法获取值。

定义方式:

· 私有成员变量:变量名以__开头(两个下划线)

· 私有成员方法:方法名以__开头(两个下划线)

class Phone:
    __current_voltage = None
    def __keep_single_core(self):
        print("保持手机单核运行")

phone = Phone()
phone.__keep_single_core()

运行结果报错,私有成员和私有变量都无法直接被类对象使用。

2、私有成员的访问

私有成员无法被类对象使用,但是可以被其他的成员使用。

class Phone:
    __current_voltage = 1

    def __keep_single_core(self):
        print("保持手机单核运行")
    def call_by_5g(self):
        if self.__current_voltage >= 1:
            print("使用5G网络进行通话")
        else:
            self.__keep_single_core()
            print("无法开启5g")

phone = Phone()
phone.call_by_5g()

运行结果表明,私有成员变量可以被正常访问

 将上述代码中的运行电压改为0.5

__current_voltage = 0.5

再次运行时:

运行结果表明:私有成员方法可以被内部其他成员访问

 3、私有成员存在的意义

在类中提供仅供内部使用的属性和方法,而不对外开放(类对象不可以使用)。

定义不直接对用户开放的属性和行为。

七、继承

1、定义

手机一代一代的更迭,新一代都是在上一代的基础上开发出来。

简单来说,就是把已有的功能(成员变量和成员方法),继承过来

2、语法:

继承分为单继承和多继承。

class 类名(父类名):

        类内容体

3、单继承

# 单继承
class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商

    def call_by_4g(self):
        print("正在使用4G网络进行通话")

class Phone2024(Phone):
    face_id = "10001"   # 面部识别ID

    def call_by_5g(self):
        print("新功能使用5G网络进行通话")

phone = Phone2024()
print(phone.producer)  # 父类中的属性
phone.call_by_4g()     # 父类中的功能
phone.call_by_5g() 

运行结果:

 4、多继承

· 一个类,可以继承多个父类,按照顺序从左往右依次继承。

语法:

class 类名(父类1,父类2,......,父类N):

        类内容体

class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商

    def call_by_4g(self):
        print("正在使用4G网络进行通话")
  
class NFCReader:
    nfc_type = "第五代"
    producer = "HM11"

    def read_nfc(self):
        print("读取NFC卡")

    def write_card(self):
        print("写入NFC卡")

class RemoteControl:
    rc_type = "红外遥控"

    def control_phone(self):
        print("红外遥控已开启")

class MyPhone(Phone, NFCReader, RemoteControl):
    pass   # pass关键字补全语法,无功能

phone = MyPhone()
phone.call_by_4g()
phone.read_nfc()
phone.control_phone()
print(phone.producer)
print(phone.nfc_type)

多继承的注意事项:

多个父类中,如果有同名的成员,那么默认以继承顺序(从左往右)为优先级。即:先继承的保留,后继承的覆盖。

示例:

class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商
  
class NFCReader:
    nfc_type = "第五代"
    producer = "HM22"
    
class MyPhone(Phone, NFCReader):
    pass   # pass关键字补全语法,无功能

phone = MyPhone()
print(phone.producer)

运行结果显示的为父类Phone中的producer值,因为Phone在NFCReader的左侧,故优先级高于NFCReader。

5、复写和使用父类成员

(1)复写

子类在继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。

即:在子类中重新定义同名的属性和方法即可。

class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商
    def call_by_5g(self):
        print("父类5G网络进行通话")


class MyPhone(Phone):
    producer = "HM33"          # 复写父类的成员属性
    def call_by_5g(self):      # 复写父类的成员方法
        print("子类5G网络进行通话")  

phone = MyPhone()
phone.call_by_5g()
print(phone.producer)

运行结果:

(2)调用父类同名成员

方式一:

· 调用父类成员

使用成员变量:父类名.成员变量

使用成员方法:父类名.成员方法(self)

class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商
    def call_by_5g(self):
        print("父类5G网络进行通话")


class MyPhone(Phone):
    producer = "HM33"          # 复写父类的成员属性
    def call_by_5g(self):      # 复写父类的成员方法
        print("子类5G网络进行通话") 
        Phone.call_by_5g(self)  # 调用父类的成员方法
        print(f"父类的厂商是{Phone.producer}")  # 调用父类的成员属性

phone = MyPhone()
phone.call_by_5g()

方式二:

· 使用super()调用父类成员

使用成员变量:super().成员变量

使用成员方法:super().成员方法()

class Phone:   # 父类
    IMEI = None # 序列号
    producer = "HM11" # 厂商
    def call_by_5g(self):
        print("父类5G网络进行通话")


class MyPhone(Phone):
    producer = "HM33"          # 复写父类的成员属性
    def call_by_5g(self):      # 复写父类的成员方法
        print("子类5G网络进行通话") 

        super().call_by_5g()   # 调用父类成员方法
        print(f"父类的厂商是{super().producer}")  # 调用父类成员属性

phone = MyPhone()
phone.call_by_5g()

注意:

只可以在子类内部调用父类的同名成员,子类的实体对象调用默认是调用子类复写的。

八、类型注解

类型注解:在代码涉及数据交互的地方,提供数据类型的注解(显示的说明)

主要功能:

 · 帮助第三方IDE工具(如Pycharm)对代码进行类型推断,协助做代码提示

 · 帮助开发者自身对变量进行类型注释(备注)

支持:

 · 变量的类型注释

 · 函数(方法)形参列表和返回值的类型注解

1、类型注解的语法

基础语法:变量:类型

# 基础类型注解

var_1:int = 10

var_2:str = "hello"

var_3:float = 3.14

var_4:bool = True

# 类类型注解

class MyClass:

    pass

stu:MyClass = MyClass()

# 基础容器类型注解

my_List:list = [1,2,3]

my_tuple:tuple = (1,2,3)

my_set:set = {1,2,3}

my_dict:dict = {"name":"张三","age":18}

# 容器类型详细注解

my_list:list[int] = [1,2,3]

my_tuple:tuple[int,str,bool] = (1,"2",True)

my_set:set[int] = {1,2,3}

my_dict:dict[str,int] = {"name":18,"age":18}

注意:

 · 元组类型设置类型详细注解,需要将每一个元素都标记出来

 · 字典类型设置类型详细注解,需要两个类型,第一个是key第二个是value

语法2:在注释中进行类型注解

# type:类型

def func():
    return 10

var_1 = random.randint(1,100)        # type:int
var_2 = json.loads('{"age:11}')      # type:dict[str,int]
var_3 = func()                       # type:int 

 2、注意事项

类型注解只是提示性的,并非决定性的。数据类型和注释类型无法对应也不会导致错误。

3、函数(方法)的类型注解

函数和方法的形参类型注解语法:

def 函数方法名(形参名:类型,形参名:类型,......)-> 返回值类型:

        pass

def add(a:int,b:int)->int:
    return a+b

 4、Union类型

使用Union[类型,......,类型],可以定义联合类型注解

Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。

使用方法: from typing import Union

from typing import Union

my_list:list[Union[int,str]] = [1,2,3,"hello"]

def func(data:Union[int,str])->Union[int,str]:
    pass

 九、多态

多态:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

           同样的行为(函数),传入不同的对象,得到不同的状态。

多态常作用在继承关系上。比如:

· 函数(方法)形参声明接收父类对象

· 实际传入父类的子类对象进行工作

即:

· 以父类做定义声明

· 以子类做实际工作

· 用以获得同一行为,不同状态

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        print("汪汪汪")

class Cat(Animal):
    def speak(self):
        print("喵喵喵")

def animal_speak(animal:Animal):
    animal.speak()

dog = Dog()
cat = Cat()
animal_speak(dog)
animal_speak(cat)

父类的Animal的speak方法,是空实现

这种设计的含义是:

· 父类用来确定有哪些方法

· 具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可称之为接口)

抽象类:含有抽象方法的类称之为抽象类

抽象方法:方法体是空实现的(pass)称之为抽象方法

抽象类(接口)

抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现

配合多态,完成

· 抽象的父类设计(设计标准)

· 具体的子类实现(实现标准)


# 抽象类
class AC:
    def cool_wind(self):
        """制冷"""
        pass
    def heat_wind(self):
        """制热"""
        pass

    def wind_on(self):
        """左右摆风"""
        pass
class Midea_AC(AC):
    def cool_wind(self):
        print("美的制冷")
    def heat_wind(self):
        print("美的制热")
    def wind_on(self):
        print("美的左右摆风")

class GREE_AC(AC):
    def cool_wind(self):
        print("格力制冷")
    def heat_wind(self):
        print("格力制热")
    def wind_on(self):
        print("格力左右摆风")
def make_cool(ac:AC):
    ac.cool_wind()

midea_ac = Midea_AC()
gree_ac = GREE_AC()
make_cool(midea_ac)   # 输出:美的制冷
make_cool(gree_ac)    # 输出: 格力制冷

抽象类的作用:

多用于做顶层设计(设计标准),以便子类做具体的实现

也是对子类的一种软约束,要求子类必须复写(实现)父类的一些方法,并且配合多态去使用,就可以获得不同的工作状态。

  • 15
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值