十、面向对象
【面向对象的三大特性:封装、继承、多态】
1.初识类(Car)
【理解】
- 设计一个类:(类似设计一张表格)
- 创建一个对象:(类似打印一张表格)
- 对象属性进行赋值:(类似填写表格)
class Student:
name = None
age = None
gender = None
def introduce(self, speciality):
print(f"Hello! My name is {self.name},I'm good at playing {speciality}")
stu1 = Student()
stu1.name = "Li"
stu1.age = 20
stu1.gender = "男"
stu1.introduce("guitar")
- 类的定义:
class 类名称:
类的属性
类的方法
- 创建类对象:
对象 = 类名称()
- 方法定义:
def 方法名(self, 形参1, 形参2, ……)
方法体
【定义到类内部的函数称为方法】
注意:
特殊参数self指代的是对象本身,代表当前对象的地址,能避免非限定调用时找不到访问对象或变量;
必须存在。在方法内部访问类的成员变量必须使用self,若是外部参数则直接访问;
但是该名称不是唯一确定的,self不是关键字,可以定义为如a、b、c等其他名字;
调用成员方法时,可以不用给self传参。
2.__init__()构造方法
python类可以使用:__init__()方法,实现在创建类对象时,会自动执行、将传入参数自动传递给__init__()方法使用。
class Student:
'''
# 可省略
name = None
age = None
gender = None
'''
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
print("创建一个类对象")
def introduce(self, speciality):
print(f"Hello! My name is {self.name},I'm good at playing {speciality}")
stu1 = Student("Li", 20, "男")
stu1.introduce("guitar")
3.魔术方法
python内置的类方法,具有各种特殊功能。
- __str__()字符串方法
返回值为:字符串
当类对象需要被转换为字符串之前,可以输出内存地址;也可控制类转换为字符串的行为。
- __lt__()小于符号比较方法
传入参数为:other和另一个对象
返回值为:True或False
直接对两个类对象无法比较,但是使用该方法可以完成大于和小于两种符号比较。
- __le__()小于等于比较符号方法
传入参数为:other和另一个对象
返回值为:True或False
与__lt__()方法类似,使用该方法可以完成大于等于和小于等于两种符号比较。
- __eq__()等于比较运算符方法
传入参数为:other和另一个对象
返回值为:True或False
不实现__eq__()方法,对象间可以比较,不过是比较内存地址;实现__eq__()方法,可以按照自定义内容进行比较。
class Student:
'''
# 可省略
name = None
age = None
gender = None
'''
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
print("创建一个类对象")
def introduce(self, speciality):
print(f"Hello! My name is {self.name},I'm good at playing {speciality}")
# __str__魔术方法
def __str__(self):
return f"name:{self.name}, age:{self.age}"
# __lt__魔术方法
def __lt__(self, other):
return self.age < other.age
# __le__魔术方法
def __le__(self, other):
return self.age <= other.age
# __eq__魔术方法
def __eq__(self, other):
return self.age == other.age
stu1 = Student("Li", 20, "男")
stu2 = Student("Wang", 18, "男")
stu1.introduce("guitar")
print(stu1) # 若不使用__str__魔术方法则仅打印内存地址,使用则能按照__str__方法中的内容形式打印
print(stu1 > stu2) # True
print(stu1 < stu2) # False
print(stu1 >= stu2)# True
print(stu1 <= stu2)# False
print(stu1 == stu2)# False
4.封装
将现实世界中事物的属性与行为对应到类中成员的属性与成员方法。完成程序对现实世界的描述。
包括【公开属性行为、非公开属性行为】
-
公开属性行为:
-
非公开属性行为:类中提供私有成员的形式
定义私有成员:
私有成员变量(/方法):变量名(/方法名)以双下划线__开头。
类对象(外部)无法访问私有成员变量和方法,但是类中的其他成员(内部)可以访问。
class Cup:
__color = "red"
def __set_color(self):
print(f"The cup is {self.__color}")
def change_color(self):
if self.__color == "blue": # 访问了私有成员变量
print("The color is changed!")
else:
self.__set_color() # 访问了私有成员方法
cup = Cup()
cup.change_color() # 返回The cup is red
5.继承
两个或者多个类之间的父子关系,子类继承了父类所有公有数据属性和方法,并可以为子类编写代码扩充额外功能。
【包括单继承、多继承】
- 单继承
class 子类名(父类名):
类内容体
class iPad2023:
memory = 128
def pad_memory(self):
print(f"The memory is {self.memory}GB")
class iPad2024(iPad2023):
pixel = 10000
def pad_pixel(self):
print(f"The pixel is {self.pixel}")
ipad = iPad2024()
ipad.pad_memory()
ipad.pad_pixel()
"""
输出内容:
The memory is 128GB
The pixel is 10000
"""
- 多继承:
一个子类可以继承多个父类。
注意:多个父类中,如果有同名的成员属性或成员方法,默认以从左到右的优先级继承。
class 子类名(父类名1,父类名2,……):
类内容体
- 复写:
子类继承父类的成员属性和成员方法后,如果需要修改,称为复写。
在子类中重新定义与父类中同名的属性或方法。
class iPad2023:
memory = 128
def pad_memory(self):
print(f"The memory is {self.memory}GB")
class iPad2024(iPad2023):
pixel = 10000
memory = 256 # 复写父类的属性
def pad_pixel(self):
print(f"The pixel is {self.pixel}")
def pad_memory(self):
print("复写父类的方法") # 复写父类的方法
ipad = iPad2024()
ipad.pad_memory()
ipad.pad_pixel()
- 调用父类同名成员
调用成员变量:父类名.成员变量 或者 super().成员变量
调用成员方法:父类名.成员方法(self) 或者 super().成员方法()
class iPad2023:
memory = 128
def pad_memory(self):
print(f"The memory is {self.memory}GB")
class iPad2024(iPad2023):
pixel = 10000
memory = 256 # 复写父类的属性
def pad_pixel(self):
print(f"The pixel is {self.pixel}")
def pad_memory(self):
print("复写父类的方法") # 复写父类的方法
# 方法一
print(f"调用父类的成员变量1:{iPad2023.memory}GB") # 调用父类成员变量
iPad2023.pad_memory(self) # 调用父类成员方法
# 方法二
print(f"调用父类的成员变量2:{super().memory}GB")
super().pad_memory()
ipad = iPad2024()
ipad.pad_memory() # 调用复写父类方法
ipad.pad_pixel() # 调用子类方法
"""
输出结果:
复写父类的方法
调用父类的成员变量1:128GB
The memory is 256GB
调用父类的成员变量2:128GB
The memory is 256GB
The pixel is 10000
"""
6.多态
指多种状态,理解成:完成同样的行为(调用同样的函数),传入不同的对象,得到不同的状态。
- 应用一:多态常用在继承关系——“父债子偿”
如:函数(方法)形参声明接收父类对象、实际向函数传入父类的子类对象进行操作。
即:用父类做定义声明,用子类做实际操作,获得同一行为、不同状态。
- 应用二:用在抽象类(接口)中
抽象方法:即方法体是空实现(pass)
抽象类:含有抽象方法的类
将多态运用在抽象类中,即父类定义的方法是空实现(pass),目的是将具体的方法实现留给子类自行决定
举例:对于当代一部手机的制作,假设其基础设计是电池、屏幕、操作系统……
则不同的手机厂商可以打造自己品牌的操作系统,也可以设计不同的屏幕(如刘海屏、挖孔屏、水滴屏等)。即父类定义了基础设计框架(方法),子类复写设计自己实现的具体方法。
# 抽象类做顶层设计,一般不用它来构建对象,而用其子类
class Phone:
def phone_screen(self):
pass
def phone_OS(self):
pass
class HuaWei(Phone):
def phone_screen(self):
print("The screen is Water-drop-screen")
def phone_OS(self):
print("The OS is HarmonyOS")
class Apple(Phone):
def phone_screen(self):
print("The screen is OLED screen")
def phone_OS(self):
print("The OS is IOS")
def info(phone: Phone):
phone.phone_screen()
phone.phone_OS()
phone1 = HuaWei()
phone2 = Apple()
info(phone1)
info(phone2)
"""
# 输出结果:
The screen is Water-drop-screen
The OS is HarmonyOS
The screen is OLED screen
The OS is IOS
"""
【记录学习过程的笔记,欢迎大家一起讨论,会持续更新】