一 property 装饰器
class People:
def __init__(self,name,weight,height):
self.name = name
self.weight = weight
self.height = height
def bmi(self):
self.bmi = self.weight/(self.height**2)
return self.bmi
people = People('gui',51,1.67)
print(people.bmi())
# 按照人类的思维来想,bmi应该是数据属性,不是函数属性,所以为了让人能够按照人的思维去使用,作为设计者应该在程序内部进行设计,让使用者认为bmi就是数据属性
class People:
def __init__(self,name,weight,height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight / (self.height ** 2)
people = People('gui',51,1.67)
print(people.bmi)
class People:
def __init__(self,name):
self.__name = name
def get_name(self):
print(self.__name)
def set_name(self,new_name):
if type(new_name) is str:
self.__name = new_name
print(self.__name)
else:
print('需要字符串格式')
def del_name(self):
print('不允许删除')
name = property(get_name,set_name,del_name)
people = People('gui')
people.name # 人类思维:people.name
people.name = 123 # 人类的思维 people.name = new_name
del people.name # 人类的思维del people.name
# 案例三
class People:
def __init__(self,name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self,new_name):
self.__name = new_name
@name.deleter
def name(self):
print('不能删除')
people = People('haha')
print(people.name)
people.name = 'gui'
print(people.name)
del people.name
二 继承与派生
1 什么是继承
继承是一种创建新类的方式,新建的类可称为子类或者派生类,父类又可称为基类或者超类,子类会遗传弗雷的属性
python支持多继承,新建的类可以继承一个或多个父类
class Parent1:
x = 111
class Parent2:
pass
class Sub(Parent1): # 单继承
pass
class Sun(Parent1,Parent2): # 多继承
pass
# __bases__查看子类继承的所有的父类
print(Sub.__bases__)
print(Sun.__bases__)
注意:
在python2中有新式类和经典类之分
新式类:继承了object的子类,以及该子类的子类、子子类...
经典类:没有继承object类的子类,以及该子类的子类、子子类
在python3中没有继承任何类,那么会默认继承object类,所以在python3中所有的类都是新式类
2 为何要用继承
用来解决类与类之间的代码重复问题
3 如何实现继承
class Student:
school = 'old_boy'
def __init(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def choose(self):
print(f'{self.name}正在选课')
class Teacher:
school = 'old_boy'
def __init__(self, name, age, sex,salary,level):
self.name = name
self.age = age
self.sex = sex
self.salary = salary
self.level = level
def score(self):
print(f'{self.name}正在打分')
# 以上代码出现重复的问题
# 基于继承解决上述两个类的代码重复问题
class OldPeople:
school = 'old_boy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 创建学生子类
# 派生的第一种:直接继承父类的属性
class Student(OldPeople):
def choice(self):
print(f'{self.name}正在选课')
# # 创建老师子类
# # 派生的第二种:覆盖父类属性
class Teacher:
school = 'old_boy'
def __init__(self, name, age, sex,salary,level):
self.name = name
self.age = age
self.sex = sex
self.salary = salary
self.level = level
def score(self):
print(f'{self.name}正在打分')
# 老师类还是有重复的代码
# 派生的第三种:指名道姓跟父类要__init__
class Teacher(OldPeople):
school = 'old_boy'
def __init__(self, name, age, sex,salary,level):
OldPeople.__init__(self,name,age,sex)
self.salary = salary
self.level = level
def score(self):
print(f'{self.name}正在打分')
tea = Teacher('hah',12,'male',100,10)
print(tea.__dict__)
三 多继承
菱形继承:不同子类拥有同一个非object的父类,而不同的子类又是另一个子类的父类
class A:
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B,C):
def test(self):
print('from D')
# 类D及类D的对象访问属性都是参照该类的mro列表
print(D.mro())
总结:类相关的属性查找(类名.属性,该类的对象.属性),都是参照该类的mro
如果多继承是非菱形继承,经典类与新式的属性查找顺序一样:都是一个分支一个分支地找下去,然后最后找object
如果多继承是菱形继承,经典类与新式类的属性查找顺序不一样:
# 经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑,即会检索大脑袋(共同的父类)
# 新式类:广度优先,会在检索最后一条分支的时候检索大脑袋
# 总结:
# 多继承到底要不用???
# 要用,但是规避几点问题
# 1、继承结构尽量不要过于复杂
# 2、推荐使用mixins机制:在多继承的背景下满足继承的什么"是"什么的关系