Python3 从零单排17_类的继承
继承 人类 -> 男人类/女人类
派生 就是在父类的基础上,子类有自己的数据或方法属性,这就是派生
子类拥有父类以及祖类(父类的父类,没上线,可以一直往上找)的一切属性(数据/方法属性),属性查找顺序,从子类本身一直往上找
class a: def f1(self): print("from a f111") def f2(self): print("from a f222") self.f1() class b(a): def f1(self): print("from b f111") print(b.__bases__) #父类列表 c = b() c.f1() #from b f111 c.f2() #from a f222 from b f111 调用f1的本质是 c.f1(),按照属性查找规则,先在子类本身找
继承原理,每个类在生成的时候解释器都会为其解析一个顺序(MRO)列表(经典类没有mro),这个列表就是对象在找属性的时候的一个顺序,从左至右。
经典类:python2中没有继承object的类以及它的子类
新式类:python2中继承了object的类以及它的子类
python3里只有新式类,如果在创建类的时候没有继承类,默认继承object,所以全是新式类
经典类 查找属性顺序为 深度优先
新式类 查找属性顺序为 广度优先
class A: def test(self): print('from A') pass class B(A): # def test(self): # print('from B') pass class C(A): # def test(self): # print('from C') pass class D(B): # def test(self): # print('from D') pass class E(C): # def test(self): # print('from E') pass class F(D,E): # def test(self): # print('from F') pass # print(F.mro()) # python3里广度优先 列表顺序 F,D,B,E,C,A,object 如果是python2里 就是 F,D,B,A,E,C,A f = F() f.test() # 查找顺序 F,D,B,E,C,A,
重用父类方法
# 1.指名道姓,不依赖继承 class Hero: def __init__(self,nickname,life_value,aggresivity): self.nickname=nickname self.life_value=life_value self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Garen(Hero): camp='Demacia' def attack(self,enemy): Hero.attack(self,enemy) #指名道姓,不依赖继承 print('from Garen Class') class Riven(Hero): camp='Noxus' g=Garen('草丛伦',100,30) r=Riven('锐雯雯',80,50) print(r.life_value) g.attack(r) print(r.life_value) class Hero: def __init__(self,nickname,life_value,aggresivity): self.nickname=nickname self.life_value=life_value self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Garen(Hero): camp='Demacia' def __init__(self,nickname,life_value,aggresivity,weapon): # self.nickname=nickname # self.life_value=life_value # self.aggresivity=aggresivity Hero.__init__(self,nickname,life_value,aggresivity) self.weapon=weapon def attack(self,enemy): Hero.attack(self,enemy) #指名道姓 print('from Garen Class') g=Garen('草丛伦',100,30,'金箍棒') print(g.__dict__) # 2.super() 依赖继承 class Hero: def __init__(self,nickname,life_value,aggresivity): self.nickname=nickname self.life_value=life_value self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Garen(Hero): camp='Demacia' def attack(self,enemy): super(Garen,self).attack(enemy) #依赖继承 super().attack(enemy) #python3的写法,可以直接写成super print('from Garen Class') class Riven(Hero): camp='Noxus' g=Garen('草丛伦',100,30) r=Riven('锐雯雯',80,50) g.attack(r) print(r.life_value)
重用__init__构造函数
class Hero: def __init__(self,nickname,life_value,aggresivity): self.nickname=nickname self.life_value=life_value self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Garen(Hero): camp='Demacia' def __init__(self,nickname,life_value,aggresivity,weapon): # self.nickname=nickname # self.life_value=life_value # self.aggresivity=aggresivity # super(Garen,self).__init__(nickname,life_value,aggresivity) super().__init__(nickname,life_value,aggresivity) self.weapon=weapon def attack(self,enemy): Hero.attack(self,enemy) #指名道姓 print('from Garen Class') g=Garen('草丛伦',100,30,'金箍棒') print(g.__dict__)
super的实质是按照当前被调用的类的mro列表一直往后面找
class A: def f1(self): print('from A') super().f1() #执行到这里的时候并不是去A的父类里找f1,而是沿着C的mro列表继续往后面找f1 class B: def f1(self): print('from B') class C(A,B): pass print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] tmp = C() tmp.f1() # from A # from B
夕闻道不如朝闻道