1、对象
(1)使用对象组织数据
在程序中是可以做到和生活中类似的,设计表格、打印表格、填写表格的组织形式的。
·设计表格,称之为:设计类(class)
eg:
class Student:
name=None # 记录学生姓名
·打印表格,称之为:创建对象
# 基于类创建对象
stu_1=Student()
stu_2=Student()
·填写表格,称之为:对象属性赋值
stu_1.name="John" # 为学生1对象赋予名称属性值
stu_2.name="Jane" # 为学生2对象赋予名称属性值
class Student:
name = None
gender = None
age = None
stu_1 = Student()
stu_1.name = "John"
stu_1.gender = "Male"
stu_1.age = 20
print(stu_1.name)
print(stu_1.gender)
print(stu_1.age)
2、类的成员方法
(1)类的组成
·类的属性,称之为:成员变量
·类的行为,称之为:成员方法
注意:函数是写在类外的,定义在类内部,但都称之为方法
(2)类与成员方法的定义语法
class 类名称:
成员变量
def 成员方法(self,参数列表):
成员方法体
对象=类名称()
(3)self
1)self关键字是成员方法定义的时候,必须填写的。
2)注意
·self表示类对象本身的意思
·在方法内部,想要访问类的成员变量,必须使用self
·self出现在形参列表中,但是不占用参数位置,无需理会
·当我们使用类对象调用方法的时候,self会自动被python 传入
class Student:
name = None
def say(self):
print(f"hello,i am {self.name}")
def say2(self,msg):
print(f"hello,i am {self.name},{msg}")
stu_1 = Student()
stu_1.name = "John"
stu_1.say()
stu_1.say2("nice to meet you")
3、类与对象的关系
类是程序中的“设计图纸”
对象是基于图纸生产的具体实体
class Clock:
id = None
price = None
def ring(self):
import winsound
winsound.Beep(2000,3000)
clock1 = Clock()
clock1.id = "1111"
clock1.price = 12
print(f"name:{clock1.id},price:{clock1.price}")
clock1.ring()
4、构造方法
(1)构造方法的名称是:
__init__,注意init前后的2个下划线符号
(2)构造方法的作用:
·构建类对象(构造类)的时候会自动运行
·构建类对象(类对象)的传参会传递给构造方法,借此特性可以给成员变量赋值
(3)注意:
·构造方法不要忘记self关键字
·在方法内使用成员变量需要使用self
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
print("student类创建了一个对象")
stu_1 = Student("John","Male",20)
# output:student类创建了一个对象
5、其他内置方法
·__init__ 构造方法,可用于创建类对象的时候设置初始化行为
·__str__ 用于实现类对象转字符串的行为
语法:
方法名:__str__
返回值:字符串
内容:自定义
当类对象需要被转换为字符串时,会输出内存地址
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
print("student类创建了一个对象")
stu_1 = Student("John","Male",20)
print(stu_1) # output:<__main__.Student object at 0x000001C77DFA1050>
print(str(stu_1)) # output:<__main__.Student object at 0x000001C77DFA1050>
那么,则会通过__str__方法,控制类转换为字符串的行为。
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
def __str__(self):
return f"name={self.name},gender={self.gender},age={self.age}"
stu_1 = Student("John","Male",20)
print(stu_1) # output:name=John,gender=Male,age=20
print(str(stu_1)) # output:name=John,gender=Male,age=20
·__lt__ 用于2个类对象进行小于或大于比较
语法:
方法名:__lt__
传入参数:other ,另一个类对象
返回值:True或False
内容:自定义
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
def __lt__(self,other):
return self.age<other.age
stu_1 = Student("John","Male",20)
stu_2 = Student("Jenny","Female",24)
print(stu_1<stu_2) # True
print(stu_1>stu_2) # False
直接对2个对象进行比较是不可以的,但是在类中实现__lt__方法,即可同时完成:小于符号和大于符号2种比较
·__le__ 用于2个类对象进行小于等于或大于等于比较
语法:
方法名:__le__
传入参数:other,另一个类对象
返回值:True或False
内容:自定义
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
def __le__(self,other):
return self.age<=other.age
stu_1 = Student("John","Male",20)
stu_2 = Student("Jenny","Female",24)
print(stu_1<=stu_2) # True
print(stu_1>=stu_2) # False
·__eq__ 用于2个类对象进行相等比较
语法:
方法名:__eq__
传入参数:other,另一个类对象
返回值:True或False
内容:自定义
class Student:
name = None
gender = None
age = None
def __init__(self,name,gerder,age):
self.age=age
self.name=name
self.gender=gerder
def __eq__(self,other):
return self.age==other.age
stu_1 = Student("John","Male",20)
stu_2 = Student("Jenny","Female",20)
print(stu_1 == stu_2) # True
6、封装
(1)定义:
将现实世界事物在类中描述为属性和方法,即为封装
(2)私有成员
1)定义:
现实事物有部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了
2)语法:
成员变量和成员方法的命名均以__作为开头即可
3)访问限制
·类对象无法访问私有成员(私有方法无法直接被类对象使用,以及私有变量无法赋值,也无法获取值)
·类中的其他成员可以访问私有成员
class Phone:
__current_voltage = 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通话")
phone1 = Phone()
phone1.call_by_5g()
# 5g通话已开启
(3)案例
# 设计手机类描述手机
class Phone:
# 提供私有成员变量:
__is_5g_enable = False # 5g状态
# 提供私有成员方法:__check_5g()
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()
"""
output:
5g关闭,使用4g网络
正在通话中····
"""
7、继承
(1)语法:class 类名(父类1,父类2,····父类N):
类内容体
子类构建的类对象,可以
·有自己的成员变量和成员方法
·使用父类的成员变量和成员方法
class Phone:
IMEI = None # 序列号
producer = "aa" # 制造商
def call_by_4g(self):
print("4g通话")
class PhoneNew(Phone):
face_id = "10001" # 面部识别ID
def call_by_5g(self):
print("新功能:5g通话")
phone = PhoneNew()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
"""
output:
aa
4g通话
新功能:5g通话
"""
(2)单继承和多继承
单继承:一个类继承另一个类
多继承:一个类继承多个类,按照顺序从左向右依次继承
多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承(先继承的保留,后继承的被覆盖)
class Phone:
IMEI = None # 序列号
producer = "aa" # 制造商
def call_by_4g(self):
print("4g通话")
class NFCReader:
nfc_type = "MIFARE"
producer = "bb"
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
my_phone = MyPhone()
print(my_phone.producer)
my_phone.call_by_4g()
my_phone.read_card()
my_phone.write_card()
my_phone.control()
"""
output:
aa
4g通话
NFC读卡
NFC写卡
遥控器开启
"""
(3)pass关键字
普通占位语句,用来保证函数或者方法或类定义的完整性,表示无内容,空的意思。
(4)复写父类成员
即在子类重新定义同名的属性或方法。
class Phone:
IMEI = None # 序列号
producer = "aa" # 制造商
def call_by_5g(self):
print("父类:5g通话")
class MyPhone(Phone):
producer = "bb" # 复写
def call_by_5g(self): # 复写方法
print("子类:5g通话")
my_phone = MyPhone()
my_phone.call_by_5g()
print(my_phone.producer)
"""
output:
子类:5g通话
bb
"""
(5)调用父类同名成员
一旦复写父类成员,那么类对象调用成员时,就会调用复写后的新成员,如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式1:
·调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:
·使用super()调用父类成员
使用成员变量:super().成员变量
使用成员方法:super().成员方法
class Phone:
IMEI = None # 序列号
producer = "aa" # 制造商
def call_by_5g(self):
print("5g通话")
class MyPhone(Phone):
producer = "bb"
def call_by_5g(self):
# print("5g通话")
print(f"父类厂商:{Phone.producer}")
Phone.call_by_5g(self)
print("关闭CPU单核模式,确保性能")
my_phone = MyPhone()
my_phone.call_by_5g()
print(my_phone.producer)
"""
output:
父类厂商:aa
5g通话
关闭CPU单核模式,确保性能
bb
"""
注意:只可以在子类内部调用父类的同名成员,子类的实体类对象调用默认是调用子类复写的
8.类型注解
(1)类型注解支持:
·变量的类型注释、
·函数(方法)形参列表和返回值的类型注释、
(2)变量的类型注解语法
语法1:变量:类型
eg:
# 基础数据类型注解:
var_1: int = 10 (为变量设置注释,显示的变量定义,一般无需注解)
var_2: int = random.randint(1,10)( 一般,无法直接看出变量类型之时
var_3: dict = json.loads(data) 会添加变量的类型注解)
var_4:Student = func()
# 类对象类型注解:
class Student:
pass
stu: student = Student()
# 基础容器类型注解:
my_list: list = [1,2,3]
my_tuple: tuple = (1,2,3)
# 容器类型详细注解:
my_list:list[int] = [1,2,3]
my_dict:dict[str,int] = {"aa":111}
my_tuple:tuple[str,int,bool] = ("aa",111,True)
注意:
·元组类型设置类型详细注解,需要将每一个元素都标记出来
·字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value
语法2:在注释中,#type:类型
eg:
var_1 = random.randint(1,10) # type: int
(3)注意事项
·类型注解只是提示性的,并非决定性的,数据类型和注解类型无法对应也不会导致错误
(4)函数(方法)可以加注解:
·形参的类型注解、
·返回值的类型注解、
(5)函数(方法)的类型注解
语法:
def 函数方法名(形参:类型,····,形参:类型)-> 返回值类型:
pass
注意,返回值类型注解的符号使用:->
eg:
·形参的类型注解
def add(x:int,y:int):
return x+y
·返回值注解
def func(data:list) -> list:
return data
(6)Union类型
1)使用Union可以定义联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。
2)使用方法:
·导包:from typing import Union
·使用:Union[类型,····,类型]
from typing import Union
my_list:list[Union[int, str]] = [1, 2, "hello"]
my_dict:dict[str,Union[int,str]] ={"name":"John","age":21}
def func(data:Union[int,str]) -> Union[int,str]:
return data
9、多态(常作用于继承关系上)
(1)多态指的是多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而得到不同的工作状态。
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("狗会汪汪")
class Cat(Animal):
def speak(self):
print("猫会喵喵")
def animal_speak(aninmal:Animal):
aninmal.speak()
dog = Dog()
cat = Cat()
animal_speak(dog) # 狗会汪汪
animal_speak(cat) # 猫会喵喵
同样行为(函数),传入不同对象,得到不同状态。
(2)抽象类(接口)
包含抽象方法的类,称之为抽象类。抽象方法是指没具体实现的方法(pass)称之为抽象方法
class Animal:
def speak(self):
pass
(3)抽象类的作用
多用于做顶层设计(设计标准),以便子类做具体实现(实现标准),也要求子类必须复写(实现)父类的一些方法。