文章目录
一、类和对象
# 创建类
class Student:
name = None # 称为成员变量
age = None
def say_hi(self):
print(f"我是{self.name}") # 称为成员方法
# 创建对象
stu_1 = Student()
# 给对象赋值
stu_1.name = "小比"
stu_1.age = 18
# 输出信息
print(stu_1.name)
print(stu_1.age)
stu_1.say_hi()
成员方法定义时self必须作为第一个变量写在参数列表里,且使用成员变量时需要加入self.,例如:
class student:
name = None
def say(self, age):
print(f"我是{self.name},{age}岁")
但传参的时候忽略self,直接从第二个形参开始传入,如上例调用时只需:
say(18)
二、构造方法
构造方法名为__init__,每次创建对象的时候会自动调用,根据其中参数为成员变量赋值,例如:
class student:
name = None
age = None # 可省略
def __init__(self, name, age):
self.name = name
self.age = age
stu = student("张三", 18)
其中最上面的成员变量声明可以省略,在构造函数中可以声明和赋值同时进行
注意构造方法也属于方法,要注意self的使用
三、魔术方法
python中有大量魔术方法,以下介绍其中的一部分:
1、__str__用于将类转换成字符串
如果不用str方法直接输出类会输出类的地址,而使用后可以自己控制输出
class student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"这位学生的信息为:{self.name},{self.age}"
stu = student("张三", 18)
print(stu)
print(str(stu))
# 如果没有__str__方法,两种输出方式都将输出类的地址
# 如<__main__.student object at 0x00000208D3E7E1D0>
# 但加入__str__方法后则能正常输出学生信息
2、__lt__用于进行大小的比较
如果直接比较类是不能比较的,而使用后可以自动完成大于和小于的比较
class student:
name = None
age = None
def __lt__(self, other):
return self.age < other.age
stu1 = student("张三", 18)
stu2 = student("李四", 19)
print(stu1 < stu2) # 结果为True
print(stu1 > stu2) # 结果为False
其中other指另一个类对象,返回值为布尔型
3、__le__用于进行“带等于”的比较
类似于__lt__方法,__le__方法用于完成大于等于和小于等于的比较
class student:
name = None
age = None
def __le__(self, other):
return self.age <= other.age
stu1 = student("张三", 18)
stu2 = student("李四", 19)
print(stu1 <= stu2) # 结果为True
print(stu1 >= stu2) # 结果为False
4、__eq__用于进行等于的比较
类似于前两种方法,__eq__用于进行等于的比较
class student:
name = None
age = None
def __eq__(self, other):
return self.age == other.age
stu1 = student("张三", 18)
stu2 = student("李四", 19)
print(stu1 == stu2) # 结果为False
p.s:如果不实现__eq__方法,类对象之间可以比较,但比较的是内存地址,故不同的类对象之间一定不相等
四、面向对象三大特性
补充:pass关键字用于补全语法,无实际意义
1、封装
在类中可以定义私有属性,只需要在成员变量或成员方法前加上两个下划线“__”即可,例如:
class student:
name = None # 公共成员变量
__age = None # 私有成员变量
def func01(self): #公共成员方法
pass
def __func02(self): # 私有成员方法
pass
# 在类外使用私有属性的不同情况
stu = student()
stu.__age = 18 # 不报错,且不生效
print(stu.__age) # 报错
stu.__func02() # 报错
私有属性不能被类对象在类外访问,但可以在同一个类中的其他成员方法使用
2、继承
继承可以让父类中的公共属性继承到子类中以节约代码量,例如:
class person:
name = None
age = None
__addr = None # 私有属性不能继承到子类
def func01(self):
class student(person):
stuid = None
# student类继承了person类的两个成员变量和一个成员函数
python中支持多继承功能,只需在类名后的()中以逗号分隔多个父类即可。在多继承中可能会出现多个父类中存在同名成员,则按照从左到右的优先级进行继承,先继承的保留,后继承的被覆盖,例如:
class person:
def eat(self):
print("调用person的eat")
class animal:
def eat(self):
print("调用animal的eat")
class student(person, animal):
pass
stu = student()
stu.eat() # 运行结果为:调用person的eat
子类在继承父类后,可以重写父类成员,重写后再调用则会调用子类中的重写的部分,但如果仍需调用父类成员,可以使用" 父类名. "的方式或者“ super() "的方式。例如:
class person:
name = "1"
def eat(self):
pass
class student(person, animal):
name = "2"
def eat(self):
person.eat(self) # 种类1
super().eat() # 种类2
print(person.name) # 种类1
print(super().name) # 种类2
如果多继承时多个父类中也有同名成员时,super()将以从上到下的优先级继承第一个同名成员,如果多次继承时父类和父类的父类中有同名成员时,将继承与子类最近的父类的同名成员
3、多态
多态指完成某个行为的时候,不同对象会得到不同的结果
抽象方法:空实现的方法(pass)
抽象类(接口):含有抽象方法的类,需要在子类中再实现
class animal:
def bark(self):
pass
class dog(animal):
def bark(self):
print("狗叫")
class cat(animal):
def bark(self):
print("猫叫")
dogs = dog()
cats = cat()
dogs.bark() # 狗叫
cats.bark() # 猫叫
五、类型注解
1、对数据的注解
对数据可以进行类型注解,既能帮助程序检查和提示,也相当于为编写者提供了注释
方式1:基本语法为:变量:类型
class student:
pass
name : str = "张三" # 表示字符串型变量name赋值为张三
age : int = 18 # 表示整型变量age赋值为18
stu : student = student() # 表示student类对象stu
my_list = list[int] # 表示列表list中的元素为整型
my_tuple = tuple[str, int, bool]
# 表示元组tuple中的元素依次为字符串,整型和布尔型
my_set = set[int] # 表示集合set中的元素为整型
my_dict = dict[str, int] # 表示字典dict中的key为字符串,value为整型
注意其中元组类型需要依次标注所有元素的类型,而字典类型需要依次标注key元素的类型和value元素的类型
方式2:基本语法为 # type: 类型
age = 18 # type : int
一般在无法看出数据类型的时候才会添加类型注解
类型注解属于备注,并不是强制语法,如果标注出了错误也是可以正常运行的, 属于可以但没必要
2、对函数的注解
对函数的形参和返回值同样可以进行类型的注解,只需在参数声明的地方加入注释即可,并且在函数最后用->写出返回值类型例如:
def func(x : int, y : int) -> int:
return x + y
3、Union类型
使用Union类型可以在注释中使用多种类型,例如:
from typing import Union
my_list : list[Union[str, int]]
# 表示在列表list中存在str或int型变量
def func(addr : Union[str, int]) ->Union[str, int]:
pass
# 表示函数传入的形参addr和返回值是str或int型变量
注意:使用Union类型联合注释之前需要进行导包操作