# 例题8-1
class Person:
number = 0 # 定义类属性,用于统计实例数量
name = '未知'
# 特殊方法 构造方法,通过类创建实例时自动被调用,初始化
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
Person.number += 1
# 析构方法
def __del__(self):
Person.number -= 1
print(f'{self.name}被析构')
# 私有成员 两个下划线开头但是不以两个下划线结尾
def __print_hello(self):
print(self.name)
print("Hello World !")
# 公有方法(实例方法)
def public_hello(self):
self.__print_hello() # 通过公有方法访问私有方法
def displayPerson(self):
print(f'姓名:{self.name} 性别:{self.gender} 年龄:{self.age}') # 打印信息
# 类方法(类和实例共享,都会默认传入类作为实参)
@classmethod
def class_print(cls):
print(cls.name)
# 静态方法(调用时要传参,没有默认)
@staticmethod
def static_print(obj):
print(obj.name)
# 继承自Person类的类,派生类可以继承基类的共有成员,但是不能继承私有成员(派生类可以直接调用基类公有成员,且需要调用基类构造函数,不会自动调用)
class Student(Person):
def __init__(self, name, gender, age, num, grade):
Person.__init__(self, name, gender, age) # 调用基类构造方法
self.num = num # 学生类新增实例属性num
self.grade = grade
def displayStudent(self):
Person.displayPerson(self) # 调用基类方法
# 由于Student继承了Person,所以Student类也有实例方法displayPerson,还可以写成:
"""Student.displayPerson(self)
self.displayPerson()"""
# 或者采用内置函数super也能调用基类方法
"""super(Student,self).displayPerson()"""
print(f'学号:{self.num} 年级:{self.grade}')
# 类的对象,成员,实例
p1 = Person('小张', '女', '18')
p1.displayPerson() # 通过实例访问实例方法,不用传入参数
print(p1.name, p1.number) # 通过实例访问类属性
print(Person.number) # 通过类访问类属性
Person.nation = '中国' # 动态添加类属性
p1.idol = 'lay' # 动态添加实例属性
print(Person.nation, """ p1.nation """, p1.idol) # 可以通过实例访问,但是会有警告
p1.nation = '韩国' # 直接覆盖共有成员,相当于创建一个新的实例成员
print(p1.nation, Person.nation) # 韩国 中国
Person.displayPerson(p1) # 通过类调用实例方法,要传入实例作为参数
Person.static_print(Person) # 通过类调用静态方法(传参) “未知”
p1.static_print(p1) # 通过实例调用静态方法(传参) “小张”
p1.static_print(Person) # 实例调用静态方法 传类参数 “未知”
Person.class_print() # 通过类调用类方法 “未知”
p1.class_print() # 通过实例调用类方法(默认传入类作为参数,与实例无关) “未知”
del p1 # 删除实例p1
print(Person.number)
# 但是不一定每次执行del 实例都会调用__del__方法
p2 = Person('小艺', '女', '20')
p2.displayPerson()
print(Person.number)
p3 = p2
p3.displayPerson()
print(Person.number)
del p2
print(Person.number)
del p3
print(Person.number)
# 类的继承
student1 = Student('小兴', '男', '35', '1007', '9')
student1.displayStudent()
student1.displayPerson() # 继承类实例调用基类公有实例方法
student1.class_print() # 继承类调用基类共有类方法
# 内置类object,任何如果没有指定父类,默认派生自该类,mro()可以用于得到某个类的继承关系,注意该内置函数返回值,要通过输出
print(Person.mro())
print(Student.mro())
# 多态(同一个方法在不同派生类中有不同的表现和行为)
# 又称“方法重载”
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B")
class C(A):
def show(self):
print("C")
# 多个基类继承而来
class D(C, B):
# 表示不在意该块内的语句,可以直接跳过(但是语句体不能空,不然会编译错误)
pass
# 列表推导式被用来创建一个包含A,B,和C类的实例的列表
ls = [number() for number in (A, B, C)]
for number in ls:
number.show()
D1, C1 = D(), C()
D1.show() # 这里继承的顺序很重要,如果B在前,就会继承B的show,如过C在前,就会继承C的show
# 特殊方法(两个下划线开头并以两个下划线结尾的方法)(公有方法)(如__init__ 运算符)重载
# ①调用__init__初始化之前,还要调用__new__创建类的实例
# ②利用print函数输出某对象,实际是调用该对象的__repr__方法
class Vector1:
def __init__(self, a, b):
self.a = a
self.b = b
class Vector2(Vector1):
def __repr__(self):
return 'vector(%d,%d)' % (self.a, self.b)
v1 = Vector1(1, 2)
print(v1) # object类的__repr__输出的是实例的地址
v2 = Vector2(1, 2)
print(v2) # 对__repr__方法重载
# 对__add__方法重载
class Vector3(Vector2):
def __add__(self, other):
return Vector3(self.a + other.a, self.b + other.b)
V3_1 = Vector3(1, 2)
V3_2 = Vector3(2, 3)
print(V3_1 + V3_2)
# 程序结束会自动调用析构函数(或重载的析构函数)
# 输出"小兴被析构"
Python类和对象,继承,多态—代码学习记录
于 2024-04-25 15:38:56 首次发布