Python 面向对象编程:类、对象与核心特性
初识对象
在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。
1 | # 在程序中设计表格,我们称之为:设计类(class) |
成员方法
类的语法:
1 | class 类名称: # class是关键字,表示要定义类 |
注意:函数是写在类外的,定义在类内部的函数习惯上称为方法
成员方法的语法
1 | class 类名称: |
self的作用:
- 表示类对象本身的意思
- 只有通过self,成员方法才能访问类的成员变量
- self出现在形参列表中,但是不占用参数位置,因此调用时无需理会
创建类对象的语法:
1 | 对象 = 类名称() |
类和对象
类和对象的关系是什么?
- 类是程序中的“设计图纸”
- 对象是基于图纸生产的具体实体
面向对象编程:使用对象进行编程。即设计类,基于类创建对象,并使用对象来完成具体的工作
构造方法
Python类可以使用:__init__()方法,称之为构造方法。
- 在创建类对象(构造类)的时候,会自动执行。
- 在创建类对象(构造类)的时候,传入参数时会自动传递给
__init__方法使用。
1 | class Student: |
注意:构造方法也是成员方法,不能忘记在参数列表中提供self
魔术方法
__init__构造方法,是Python类内置的方法之一。
这些内置的类方法各自有各自特殊的功能,称之为魔术方法
__str__字符串魔术方法
当类对象需要被转换为字符串时,会输出其内存地址
1 | class Student: |
但是内存地址没有多大作用,可以通过str 方法,控制类转换为字符串的行为
1
2
3
4
5
6
7
8
9
10
11class Student:
def __init__ (self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"student类对象,name={self.name}, age={self.age}"
student = Student("周杰轮", 11)
print(student) # 结果:Student类对象,name=周杰轮,age=11
print(str(student)) # 结果:Student类对象,name=周杰轮,age=l1
__lt__小于符号魔术方法
两个对象之间不可以直接进行比较
1
2
3
4
5
6
7class Student:
def __init__ (self, name, age):
self.name = nameself.age = age
stu1 = Student("周杰伦",11)
stu2 = Student("林俊杰",13)
print(stul < stu2) # 此处无法比较,会直接报错
此时需要在类中实现__lt__方法,即可同时完成:小于符号和大于符号2种比较
1
2
3
4
5
6
7
8
9
10class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __lt__(self, other):
return self.age < other.age
stu1 = Student("周杰伦",11)
stu2 = Student("林俊杰",13)
print(stu1 < stu2) # 结果:True
print(stu1 > stu2) # 结果:False
__le__小于等于符号魔术方法
1 | class Student: |
__eq__比较运算符魔术方法
1 | class Student: |
封装
面向对象包含3大主要特性:
- 封装
- 继承
- 多态
封装是指将现实世界事物在类中描述为属性和方法。
现实事物的部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求
定义私有成员:成员变量和成员方法的命名均以__作为开头
1 | class Phone: |
注意:类对象无法访问私有成员,类中的其它成员可以访问私有成员
继承
继承的基础语法
继承:将从父类那里继承(复制)来成员变量和成员方法(不含私有)
子类构建的类对象,可以
- 有自己的成员变量和成员方法
- 使用父类的成员变量和成员方法
单继承和多继承
类的单继承语法:
1 | class 类名(父类名): |
类的多继承语法:
1 | class 类名(父类1, 父类2, ..., 父类N): |
注意:多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承
pass
pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
复写和使用父类成员
复写
对父类的成员属性或成员方法进行重新定义
调用父类成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员。
如果需要使用被复写的父类的成员,需要特殊的调用方式:
1 | # 方式1:调用父类成员 |
类型注解
类型注解支持:
- 变量的类型注解
- 函数(方法)的形参和返回值的类型注解
变量的类型注解
语法1:变量:类型
1 | # 基础数据类型注解 |
语法2:在注释中,#type:类型
1 | # 在注释中进行类型注解 |
注意:类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会导致编译错误
函数(方法)的类型注解
形参的类型注解
1 | def add(x: int, y: int): |
返回值的类型注解
1 | def 函数方法名(形参: 类型,......, 形参:类型) -> 返回值类型: |
Union联合类型注解
1 | # 变量的联合类型注解 |
多态
多态常用在继承关系上。
- 以父类做定义声明
- 以子类做实际工作
- 用以获得同一行为,不同状态
这种写法,就叫做抽象类(也可以称之为接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法