面向对象
创建第一个类
# 设计一个类
class Student:
name = None
sex = None
age = None
# 在类中定义一个方法
def sai_hi(self):
print(f"Hi大家好,我是{self.name}")
# 创建一个对象
stu_1 = Student()
# 对象属性进行赋值
stu_1.name = "金清泽"
stu_1.sex = "男"
stu_1.age = 22
# 获取对象中记录的信息
print(stu_1.name)
print(stu_1.sex)
print(stu_1.age)
类的基本语法
基本语法
class 类名称:
类的属性
类的行为
创建对象的语法
对象 = 类名称()
成员方法的定义语法
def 方法名(self,形参1,...形参n):
方法体
类和对象
类可以包含属性和行为,实用类描述现实世界事物是非常合适的。
类知识一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作,这种套路称为:面向对象编程。
class Clock:
id = None
price = None
def ring(self):
import winsound
winsound.Beep(2000,3000)
# 构建2个闹钟对象让其工作
clock1 = Clock()
clock1.id = "001001"
clock1.price = 19.99
clock1.ring()
clock2 = Clock()
clock2.id = "001002"
clock2.price = 19.99
构造方法
python 类恶意使用:__ init__()方法,称之为构造方法。
可以实现:
- 在创建类对象(构造类)的时候,会自动执行。
- 在创建类对象(构造类)的时候,将传入参数自动传递给__ init__方法使用。_
构造类时传入的参数会自动提供给 init 方法,构建类的时候 init 方法会自动执行。
其他内置方法
__ str__ 字符串方法
如果直接将对象转为字符串,那么将获得该对象的内存地址。
想要获得对应的值,需要写 str 方法。
__ lt__ 小于符号比较方法
直接对2个对象进行比较是不可以的,但是在类中实现 lt 方法,即可同时完成:小于符号和大于符号2种比较。
__ le__ 小于等于符号比较方法
le 可用于:<=、>=两种比较运算符上。
__ eq__ 比较运算符
不实现 eq 方法,对象之间可以比较,但是比较的是内存地址,也就是不同的对象比较一定会是 False 的结果。
实现了 eq 方法,就可以按照自己的想法来决定两个对象是否相等了。
class Student:
name = None
age = None
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age}"
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __eq__(self, other):
return self.age == other.age
stu1 = Student("金清泽", 21)
stu2 = Student("赵悦", 21)
# 未加str 魔术方法之前
# <__main__.Student object at 0x0000013C77645390>
# 加入str 魔术方法后
# Student类对象,name:金清泽,age:21
print(stu1)
print(str(stu1))
# 比较
print(stu1 < stu2)
print(stu1 <= stu2)
print(stu1 == stu2)
封装
面向对象的
私有成员
类中提供了私有成员的形式来支持
- 私有成员变量
- 私有成员方法
定义私有成员的方式,只需要以两个下划线开头。
私有方法无法直接被类对象使用,无法赋值,也无法获取值。
class Phone:
__current_voltage = 0
def __keep_sing_core(self):
print("让CPU以单核模式运行")
def call_by_5g(self):
if self.__current_voltage >= 1:
print("5G通话以开启")
else:
self.__keep_sing_core()
print("电量不足,无法使用5G通话,并已设置为单核运行进行省电。")
phone= Phone()
phone.call_by_5g()
访问限制
类对象无法访问私有成员,但是类中的其他成员可以访问私有成员。
继承
继承表示将从父类那里继承(复制)来成员变量和成员方法(不含私有)
继承分为单继承和多继承。
语法
# 单继承
class 类名(父类名):
类内容体
# 多继承
class 类名(父类1,父类2,...,父类n):
类内容体
多继承中如果父类有同名方法或属性,先继承的优先级高于后继承。
# 演示单继承
class Phone:
IMEI = None
producer = "ITCast"
def call_by_4g(self):
print("4g通话")
class Phone2022(Phone):
face_id = "10001"
def call_by_5g(self):
print("2022年新功能:5g通话")
phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
# 演示多继承
class NFCReader:
nfc_type = "第五代"
producer = "HM"
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
phone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()
# 演示多继承下,父类成员名一致的场景
# 如果有重名,则以左边的优先
print(phone.producer)
复写
子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。
即:在子类中重新定义同名的属性或方法即可。
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员。
# 定义子类,复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA"
def call_by_4g(self):
print("开启CPU单核模式,确保通话的时候省点")
print("使用5g网络进行通话")
print("关闭CPU单核模式,确保性能")
phone = MyPhone()
phone.call_by_4g()
print(phone.producer)
如果需要使用被复写前的父类成员,需要特殊的调用方式:
方式1
调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2
使用super()调用父类成员
使用成员变量:super().成员变量
使用成员方法:super().成员方法()
# 定义子类,复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA"
def call_by_4g(self):
print("开启CPU单核模式,确保通话的时候省点")
# 调用父类的成员
# 方式1
print(f"父类的厂商是:{Phone.producer}")
Phone.call_by_4g(self)
# 方式2
print(f"父类的厂商是:{super().producer}")
super().call_by_4g()
print("关闭CPU单核模式,确保性能")
类型注解
python 在 3.5 版本的时候就引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。
类型注解:在代码中设计数据交互的地方,提供数据类型的注解(显式的说明)。
主要功能:
- 帮助第三方IDE 工具对代码进行类型推断,协助做代码提示
- 帮助开发者自身对变量进行类型注释
支持:
- 变量的类型注解
- 函数(方法)形参列表和返回值的类型注解
一般,无法直接看出变量类型之时会添加变量的类型注解。
为变量设置类型注解
基础语法:变量:类型
# 基础数据类型注解
var_1: int = 10
var_2: str = "Hello"
var_3: bool = True
# 类型对象类型注解
class Student:
pass
stu: Student = Student()
# 基础容器类型注解
my_list:list = [1,2,3]
my_tuple:tuple = (1,2,3)
my_dict:dict = {"姓名":"金清泽"}
# 容器类型详细注解
my_list:list[int] = [1,2,3]
my_tuple:tuple[int,str,bool] = (1,"12",True)
my_dict:dict[str,int] = {"姓名":"金清泽"}
注意
元组类型设置类型详细注解,需要将每一个元素都标记出来。
字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value。
除了使用 变量:类型,这种语法做注解外,也可以在注释中进行类型注解。
语法:
#type:类型
# 在注释中进行类型注解
var_1 = random.randint(1,10) # type:int
var_2 = json.loads('{"name":"zhangsan"}') # type: dict[str,str]
def func():
pass
var_3 = func() # type:int
类型注解之时提示性的,并非决定性的。
数据类型和注解类型无法对应也不会导致错误。
为函数进行类型注解
对函数(方法)的形参进行注解
语法
def 函数方法名(形参名:类型,形参名:类型,...):
pass
# 对函数的形参进行类型注解
def add(x: int, y: int):
return x + y
add()
对函数(方法)的返回值进行注解
def 函数方法名(形参名:类型,形参名:类型,...) -> 返回值类型:
pass
# 对函数的返回值进行类型注解
def func(data:list) -> list:
return data
Union 类型
基本语法
Union[类型,类型,…,类型]
# 使用Union类型,必须先导包
from typing import Union
my_list :list [Union[int,str]] = [1,2,"jqz","Hello"]
def func(data:Union[int,str]) -> Union[int,str]:
pass
func()
多态
多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
多态常作用与继承关系上。
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对象"""
animal.speak()
# 演示多态,使用2个子类对象来调用函数
dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)
抽象类(接口)
在设计类的方法时,是空实现。
这样的设计是让父类来确定有哪些方法,具体的方法实现由子类自行决定。
这种写法就叫做抽象类(也可以称之为接口)。
抽象类
含有抽象方法的类称之为抽象类。
抽象方法
方法体是空实现的(pass)称之为抽象方法。
抽象类就好比定义了一个标准,包含了一些抽象的方法,要求子类必须实现。
# 演示抽象类
class AC:
def cool_wind(self):
"""制冷"""
pass
def hot_wind(self):
"""制热"""
pass
def swing_l_r(self):
"""左右摆风"""
pass
class Midea_AC(AC):
def cool_wind(self):
print("美的空调制冷")
def hot_wind(self):
print("美的空调制热")
def swing_l_r(self):
print("美的空调左右摆风")
class GREE_AC(AC):
def cool_wind(self):
print("格力空调制冷")
def hot_wind(self):
print("格力空调制热")
def swing_l_r(self):
print("格力空调左右摆风")
def make_cool(ac:AC):
ac.cool_wind()
midea_ac = Midea_AC()
gree_ac = GREE_AC()
make_cool(midea_ac)
make_cool(gree_ac)