面向对象
一、初识对象
- 设计类(class),相当于设计表格
- 创建对象,相当于打印生产表格
- 对象赋值属性,相当于填写表格
python
# 创建对象,相当于设计一张登记表
class Student:
name = None
gender = None
age = None
# 创建对象,相当于打印一张表
stu_1 = Student()
# 为对象属性赋值,相当于填表
stu_1.name = "周杰伦"
stu_1.gender = "M"
stu_1.age = 22
# 获取对象中记录的信息
print(stu_1.name)
print(stu_1.gender)
print(stu_1.age)
二、成员方法
1、类的定义和使用
类的使用语法
python
class 类名称:
类的属性
类的行为
- class是关键字,表示要定义类了
- 类的属性,即定义在类中的变量(成员变量)
- 类的行为,即定义在类中的函数(成员方法)
创建类对象的语句:
python
对象 = 类名称()
成员方法定义语法
python
def 方法名(self,形参1,......,形参N):
方法体
- self关键字是成员方法定义时,必须填写的,表示类对象自身的意思
- 当我们使用类对象第哦啊用方法的时候,self会自动被Python传入
- 在方法内部,想要访问类的成员变量,必须使用self
python
# 创建对象,相当于设计一张登记表
class Student:
name = None
gender = None
age = None
def say_hello(self):
print(f"Hello World,我是{self.name}")
# 创建对象,相当于打印一张表
stu_1 = Student()
# 为对象属性赋值,相当于填表
stu_1.name = "周杰伦"
stu_1.gender = "M"
stu_1.age = 22
# 获取对象中记录的信息
stu_1.say_hello()
2、类和方法
类可以包含属性和行为
类是程序中的"设计图纸"
面向对象变成是使用对象进行编程,即,射设计类,基于类创建对象
二、构造方法
Python类可以使用:__init__()方法,称之为构造方法
可以实现:
- 在创建类对象(构建类)的时候,会自动执行
- 在创建类对象(构建类)的时候,将传入参数自定传递给
__init__方法使用
python
class Student:
def say_hello(self):
print(f"Hello World,我是{self.name}")
def __init__(self, name, gender, age):
# 具有赋值和定义的功能,之前的定义可以省略
self.name = name
self.gender = gender
self.age = age
print("Student类创建了一个对象")
stu_1 = Student("周杰伦", 'M', 22)
运行结果:

三、常见的类内置方法
__init__构造方法就是Python类内置的方法之一
这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法
常见魔术方法:
-
__init__:构造方法 -
__str__:字符串方法pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where student = Student("周杰伦", 18, "上海") print(student) # 结果:<__main__.Student object at 0x000001FB33268C20>当类对象需要被转换成字符串的时候,会输出内存地址
内存地址不是我们想要的,就可以通过
__str__方法,控制类转换为字符串的行为 方法名:
__str__ 返回值:字符串
内容:自行定义
pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where def __str__(self): return f'我是{self.name},我{self.age}岁,我现在住在{self.where}' student = Student("周杰伦", 18, "上海") print(student) # 结果:我是周杰伦,我18岁,我现在住在上海 -
__lt__:大于、小于符号比较pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where student1 = Student("周杰伦", 18, "上海") student2 = Student("林俊杰", 20, "北京") print(student1 < student2) # 结果: # Traceback (most recent call last): # File "D:\study\pycharm\pycharm_project\study.py", line 306, in <module> # print(student1 < student2) # ^^^^^^^^^^^^^^^^^^^ # TypeError: '<' not supported between instances of 'Student' and 'Student'直接将2个对象进行比较是不可以的,但是在类中实现
__lt__方法,即可同时完成:小于和大于符号的2种比较 方法名:
__lt__ 传入参数:other,另一个对象
返回值:True或False
内容:自行定义
pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where def __lt__(self, other): return self.age < other.age student1 = Student("周杰伦", 18, "上海") student2 = Student("林俊杰", 20, "北京") print(student1 < student2) # 结果:True print(student1 > student2) # 结果:False -
__le__:小于等于、大于等于符号比较相较于
__lt__多了等于的比较 方法名:
__le__ 传入参数:other,另一个对象
返回值:True或False
内容:自行定义
pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where def __le__(self, other): return self.age < other.age student1 = Student("周杰伦", 18, "上海") student2 = Student("林俊杰", 20, "北京") print(student1 <= student2) # 结果:True print(student1 >= student2) # 结果:False -
__eq__:==符号比较正常来说,对象之前比较的是内存地址,也就是说==比较,结果一定是False
pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where student1 = Student("周杰伦", 18, "上海") student2 = Student("周杰伦", 18, "上海") print(student1 == student2) # 结果:False使用
__eq__方法,按照自己的想法来决定2个对象是否相等 方法名:
__eq__ 传入参数:other,另一个对象
返回值:True或False
内容:自行定义
pythonclass Student: def __init__(self, name, age, where): self.name = name self.age = age self.where = where def __eq__(self, other): return self.age == other.age student1 = Student("周杰伦1", 18, "上海") student2 = Student("周杰伦2", 18, "上海") student3 = Student("林俊杰3", 20, "北京") print(student1 == student2) # 结果:True print(student1 == student3) # 结果:False
四、封装
封装指的是将现实事务的:属性、行为,封装到类中,描述为:成员变量、成员方法,从而完成程序对于现实世界的描述
1、私有成员
类中提供私有成员的形式来支持,私有成员变量、私有成员方法
命名规则 :
- 私有成员变量:变量名以__开头(两个下划线)
- 私有成员方法:方法名以__开头(两个下划线)
访问限制
- 类对象无法访问私有成员
- 类中的其他成员可以访问私有成员
使用私有成员
- 错误使用方法:
python
class phone:
# 序列号
IMEI = None
# 厂商
producer = None
# 当前电压
__current_voltage = None
def call_by_5g(self):
print("5g通话已开启")
def __keep_single_core(self):
print("让cpu以单核模式运行以节约电量")
# 创建对象
phone = phone()
# 使用私有方法
# 报错
phone.__keep_single_core()
# 私有变量赋值
# 不报错,但无效
phone.__current_voltage = 10
# 获取私有变量值
# 报错,无法使用
print(phone.__current_voltage)
- 正确使用方法
python
class phone:
# 序列号
IMEI = None
# 厂商
producer = None
# 当前电压
__current_voltage = 0.1
def __keep_single_core(self):
print("让cpu以单核模式运行以节约电量")
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()
练习题
设计带有私有成员的手机
设计一个手机类,内部包含:
- 私有成员变量
__is_5g_enable,类型为bool,True表示开启5g,False表示关闭5g - 私有成员方法:
__check_5g(),会判断私有成员__is_5g_enable的值- 若为True,打印输出:
5g开启 - 若为False,打印输出:
5g开启,使用4g网络
- 若为True,打印输出:
- 公开成员方法:
call_by_5g(),调用它会执行- 调用私有成员方法:
__check_5g(),判断5g网络状态 - 打印输出:
正在通话中
- 调用私有成员方法:
运行结果:5g关闭,使用4g网络
正在通话中...
通过完成这个类的设计和使用,体会封装中私有成员的作用
- 对用户公开的,
call_by_5g()方法 - 对用户隐藏的,
__is_5g_enable私有变量和__check_5g私有成员
python
# 设计一个类,用来描述手机
class Phone:
# 提供私有成员变量:__is_5g_enable
__is_5g_enable = True
# 提供私有成员方法:
def __check_5g(self):
if self.__is_5g_enable:
print("5g开启")
else:
print("5g关闭,使用4g网络")
# 提供公开成员方法:call_by_5g()
def call_by_5g(self):
self.__check_5g()
print("正在通话中...")
phone = Phone()
phone.call_by_5g()
五、继承
继承:将父类那里继承(复制)来成员变量和成员方法(不含私有)
1、继承的基本语法
python
class 类名(父类名)
类内容体
2、单继承
python
# 单继承示例
class Phone:
# 序列号
IMEI = None
# 厂商
producer = "RAY"
def call_by_4g(self):
print("4g通话")
class Phone2026(Phone):
# 面部识别id
face_id = '10001'
def call_by_5g(self):
print("2026年性能功能:5g通话")
phone = Phone2026()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
3、多继承
Python中类之间也支持多继承,即:一个类,可以继承多个父类
python
class 类名(父类1, 父类2, ......, 父类N):
类内容体
python
# 多继承示例:
class Phone:
# 序列号
IMEI = None
# 厂商
producer = "RAY"
def call_by_4g(self):
print("4g通话")
class Phone2026(Phone):
# 面部识别id
face_id = '10001'
def call_by_5g(self):
print("2026年性能功能:5g通话")
phone = Phone2026()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
class NFCReader:
nfc_type = "第五代"
producer = "Ray"
def read_card(self):
print("NFC读卡")
def write_card(self):
print("NFC写卡")
class RemoteControl:
rc_type = "红外遥控"
def control(self):
print("红外遥控已开启")
class MyPhone(Phone, NFCReader, RemoteControl):
# pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容、空的意思
pass
phone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()
# 运行结果:
# RAY
# 4g通话
# 2026年性能功能:5g通话
# 4g通话
# NFC读卡
# NFC写卡
# 红外遥控已开启
多继承注意事项:
多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即:先继承的保留,后继承的覆盖
4、复写和使用父类成员
复写
子类继承父类的成员属性和成员方法后,如果对其"不满意",那么可以进行复写。即:在子类中重新定义同名的属性或方法即可。
python
# 复写
class phone:
IMEI = None
producer = "RAY"
def call_by_5g(self):
print("父类的5g通话")
# 定义子类,复写父类成员
class MyPhone(phone):
# 复写父类的成员属性
producer = "HAHA"
def call_by_5g(self):
print("子类的5g通话")
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
# 运行结果:
# 子类的5g通话
# HAHA
调用父类同名成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员。如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式1:
调用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方法2:
使用super()调用父类方法
使用成员变量:super().成员变量
使用成员方法:super.成员方法()
python
#调用示例
class phones:
IMEI = None
producer = "RAY"
def call_by_5g(self):
print("父类的5g通话")
# 定义子类,复写父类成员
class MyPhone(phones):
# 复写父类的成员属性
producer = "HAHA"
def call_by_5g(self):
print("子类的5g通话")
print(f"子类:{phones.producer}")
phones.call_by_5g(self)
print(f"子类:{super().producer}")
super().call_by_5g()
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
# 运行结果:
# 子类的5g通话
# 子类:RAY
# 父类的5g通话
# 子类:RAY
# 父类的5g通话
# HAHA
六、类型注解
类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)
主要功能:
- 帮助第三方IDE对代码进行类型推断,协助做代码提示
- 帮助开发者自身对变量进行类型注释
注意事项:
类型注解只是提示性的,并未决定性的。数据类型和注解类型无法对应也不会导致错误
1、变量的类型注解
基础语法:**变量: 类型**
py
# 基础数据类型注解
var_1: int = 1
var_2: float = 2.222
var_3: bool = True
var_4: str = "Ray"
# 类对象类型注解
class Student:
pass
stu: Student = Student()
# 基础容器类型注解
my_list: list = [1, 2, 3]
my_tuple: tuple = (1, 2, 3)
my_set: set = {1, 2, 3}
my_dict: dict = {"name": "Ray"}
my_str: str = "Ray"
# 容器类型详解
mylist2: list[int] = [1, 2, 3]
my_tuple2: tuple[str, int, bool] = ("Ray", 1, True)
my_set2: set[int] = {1, 2, 3}
my_dict2: dict[str, int] = {"Ray": 666}
# 注意
# ·元组类型设置类型详细注解,需要将每一个元素都标记出来
# ·字典类型设置类型纤细注解,需要2个类型,第一个是Key,第二个是Value
2、函数(方法)的类型注解
基础语法:
python
def 函数方法名(形参名:类型,形参名:类型,......):
pass
python
# 调用示例
def add(a: int, b: int):
return a + b
同时,函数(方法)的返回值也是可以添加类型注解的
语法:
python
def 函数方法名(形参名:类型,形参名:类型,......)->返回值类型:
pass
python
# 调用示例
def func(data: list) -> list:
return data
3、Union类型
使用Union可以定义联合类型注解
使用Union类型,必须先导包
python
from typing import Union
my_list: list[Union[int, str]] = [1, 2, "Ray"]
def func(data: Union[int, str]) -> Union[int, str]:
pass
七、多态
多态,指的是:多种状态,即完成某种行为时,使用不同的对象会得到不同的状态。
多态常作用在继承关系上
比如
- 函数(方法)形参声明接收父类对象
- 实际传入父类的子类对象进行工作
即:
- 以父类做定义声明
- 以子类做实际工作
- 用以获得同一行为,不同状态
python
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("Woof!")
class Cat(Animal):
def speak(self):
print("Wow!")
dog = Dog()
cat = Cat()
dog.speak()
cat.speak()
抽象类
包括抽象方法的类,称之为抽象类
抽象方法指的是:没有具体实现的方法(pass)称之为抽象方法
抽象类的作用
多用于顶层设计(设计标准),以便子类做具体实现
也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法
并配合多态使用,获得不同的工作状态