设计表格-生产表格-填写表格
对应于程序中:设计类-创建对象-对象属性赋值
class Student:
name=None
gender=None
# 基于类创建对象
stu_1=Student()
stu_2=Student()
# 对象属性进行赋值
stu_1.name="张三"
stu_2.name="李四"
# 获取对象中记录的信息
print(stu_1.name)
可以使用类去封装对象属性,并基于类创建出一个个对象来使用
类的使用语法
class 类名称: # class为关键字
类的属性 #定义在类中的变量(成员变量)
类的行为 #定义在类中的函数(成员方法)
创建类对象的语法:
对象=类名称()
类的行为(方法):
class Student:
name=None
age=None
def say_hi(self):
print(f"我是{self.name}")
stu=Student()
stu.name="张三"
stu.say_hi() # 输出:我是张三
可以看出类不仅可以用来定义属性、记录数据,也可以定义函数、记录行为。
在类中定义成员方法和定义函数基本一致:
def 方法名(self,形参1,...,形参N)
方法体
self关键字是成员方法定义时必须写的,用来表示类对象自身的意思,当使用类对象调用方法,self会被python传入,在方法内部,要访问类的成员变量必须使用self
# 设计一个闹钟类
class Clock:
id=None
price=None
def ring(self):
import winsound
winsound.Beep(2000,3000)
# 构建2个闹钟对象并让其工作
clock1=Clock()
clock1.id="003032"
clock1.price=19.99
print(f"闹钟ID:{clock1.id},价格:{clock1.price}")
clock1.ring()
clock2=Clock()
clock2.id="003033"
clock2.price=21.99
print(f"闹钟ID:{clock2.id},价格:{clock2.price}")
clock2.ring()
python类可以使用:init()方法,称之为构造方法
可以实现:
class Studengt:
name=None
age=None
tel=None
def __init__(self,name,age,tel):
self.name=name
self.age=age
self.tel=tel
print("Student类创建了一个对象")
stu=student("张三",31,"123456")
当类对象需要被转换为字符串时,会输出内存地址
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
student=Student("张三",11)
print(student) #<__main__.Student object at 0x000002200CFD7040>
print(str(student)) #<__main__.Student object at 0x000002200CFD7040>
可以通过__str__方法,控制类转换为字符串的行为
class 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=11
直接两个对象进行比较是不可以的,但是在类中实现__lt__方法,可同时完成小于符号和大于符号比较。
class Student:
def __init__(sefl,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
class Student:
def __init__(sefl,name,age):
self.name=name
self.age=age
def __le__(self,other):
return self.age <= other.age
stu1=Student("张三",11)
stu2=Student("李四",13)
print(stu1<=stu2) # True
不实现__eq__方法,对象之间可以比较,但是是比较内存地址,即不同对象之间比较一定是False。
class Student:
def __init__(sefl,name,age):
self.name=name
self.age=age
def __eq__(self,other):
return self.age == other.age
stu1=Student("张三",11)
stu2=Student("李四",13)
print(stu1==stu2) # True
将现实世界事物在类中描述为属性和方法,即为封装。
现实事物有部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求,需要定义私有成员,成员变量和成员方法的命名均以__作为开头即可。
类对象无法访问私有成员。
类中的其他成员可以访问私有成员。
在类中提供仅供内部使用的属性和方法而不对外开放(类对象无法使用)。
# 定义一个类,内含私有成员变量和私有成员方法
class Phone:
__current_voltage=None #当前手机运行电压
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.__keep_single_core()
# print(phone.__current_voltage)
私有成员无法被类对象使用,但是可以被其它的成员使用。
# 单继承
class phone:
IMEI=None #序列号
producer=None #厂商
def call_by_4g(self):
print("4g通话")
class phone2022(phone):
face_id=True # 面部识别
def call_by_5g(self):
print("2022最新5g通话")
# 多继承
class Myphone(phone, NFCReader, RemoteControl):
pass
pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思。
class 类名(父类1, 父类2, ..., 父类N):
类内容体
多继承注意事项:多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即先继承的保留,后继承的被覆盖。
子类继承父类的成员属性和成员方法后,通过在子类中重新定义同名的属性或方法进行复写。
一旦复写父类成员,那么类对象调用成员时,就会调用复写后的新成员。
如果需要使用被复写的父类的成员,需要特殊的调用方式:
# 调用父类成员
# 使用成员变量:父类名.成员变量
# 使用成员方法:父类名.成员方法(self)
# 使用super()调用父类成员
# 使用成员变量:super().成员变量
# 使用成员方法:super().成员方法()
注意:只可以在子类内部调用父类的同名成员,字类的实体类对象调用默认调用子类复写
当调用方法进行传参的时候,ctrl+p
弹出提示:
import random
random.randint()
传入2个参数,类型是int
内置模块random的方法可以提示类型,而自定义的不可以。因为pycharm无法通过代码确定应传入什么类型,需要使用类型注解。
类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显示的说明)。帮助第三方IDE工具(如pycharm)对代码进行类型推断,协助做代码提示;帮助开发者自身对变量进行类型注释,并不会对类型做验证和判断。
支持:变量的类型注解;函数(方法)形参列表和返回值的类型注解
基础语法:变量:类型
# 基础数据类型注解
var_1:int = 10
var_2:float=3.14
var_3:bool=True
var_4:"itheima"
# 类对象类型注解
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={"itheima":666}
my_str:str="itheima"
# 容器类型详细注解
my_list:list[int]=[1,2,3]
my_tuple:tuple[str,int,bool]=("itheima",666,True)
my_set:set[int]={1,2,3}
my_dict:dict[str,int]={"itheima":666}
元组类型设置类型详细注解,需要将每一个元素都标记出来。
字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value。
为变量设置注解,显示的变量定义,一般无需注解。无法直接看出变量类型之时会添加变量的类型注解。
也可以在注释中进行类型注解
语法:# type:类型
class Student:
pass
var_1=random.randint(1,10) # type: int
var_2=json.loads(data) # type: dict[str,int]
var_3=func() # type: Student
类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会导致错误。
def func(data):
data.app
func()
在编写函数(方法),使用形参data的时候,工具没有任何提示;在调用函数(方法),传入参数的时候,工具无法提示参数类型。因为在定义函数(方法)的时候没有给形参进行注解。
函数和方法的形参类型注解语法:
同时,函数(方法)的返回值也可以添加类型注解。
def 函数方法名(形参名:类型,形参名:类型,...)->返回值类型:
pass
使用Union[类型,...,类型]
可以定义联合类型注释
from typing import Union # 必须先导包
my_list:list[Union[str,int]]=[1,2,"itheima","itcast"]
my_dict:dict[str,Union[str,int]]={"name":"张三","age":31}
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 make_noise(animal:Animal):
animal.speak()
dog=Dog()
cat=Cat()
make_noise(dog) #输出:汪汪汪
make_noise(cat) #输出:喵喵喵
多态常作用在继承关系上。比如函数(方法)形参声明接收父类对象,实际传入父类的子类对象进行工作,即以父类做定义声明、以子类做实际工作、用以获得同一行为不同状态。
抽象类(接口):包含抽象方法的类。抽象方法指没有具体实现的方法(pass)。
抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现。多用于顶层设计,以便子类做具体实现,也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法,并配合多态,完成不同的工作状态。
抽象的父类设计(设计标准);具体的子类实现(实现标准)