python学习 day20 (3月27日)----(单继承多继承c3算法)
继承:
提高代码的重用性,减少了代码的冗余
这两个写法是一样的 Wa('青蛙').walk() #青蛙 can walk wa = Wa('青蛙') wa.walk() #青蛙 can walk
1.单继承
麻烦的写法(为什么要有单继承)
如果多个类相似的情况下(每个都写一遍有大量重复 浪费麻烦)
class Tiger(object):
def __init__(self,name):
self.name = name
def walk(self):
print('%s can walk'%self.name)
def swim(self):
print('%s can swim'%self.name)
Tiger('老虎').walk()
class Swan(object):
def __init__(self,name):
self.name = name
def walk(self):
print('%s can walk'%self.name)
def fly(self):
print('%s can fly'%self.name)
Swan('鹦鹉').fly()
class Wa(object):
def __init__(self,name):
self.name = name
def walk(self):
print('%s can walk'%self.name)
def swim(self):
print('%s can swim' % self.name)
Wa('青蛙').walk() #青蛙 can walk
wa = Wa('青蛙')
wa.walk() #青蛙 can walk
class Er(object):
def __init__(self,name):
self.name = name
def walk(self):
print('%s can walk'%self.name)
def swim(self):
print('%s can swim' % self.name)
def fly(self):
print('%s can fly'%self.name)
# Er('天鹅').swim()
Er('天鹅').fly()
继承
创建一个父类
子类用父类的属性和方法 因为都差不多
子类也可以新建自己特殊的属性和方法,通过super().__init__(相同元素) 和 父类名.__init__(self,相同元素)
方法的话 自己新建 不必返回父类
class Animal(object):
def __init__(self,name,kind):
self.name = name
self.kind = kind #多了不是很好
def walk(self):
print('%s can walk'%self.name)
def swim(self):
print('%s can swim' % self.name)
def fly(self): #可以有任意个
print('%s can fly'%self.name)
class Tiger(Animal):pass
class Bird(Animal):
def __init__(self,name,kind,eyes_color): #小心 元素必须与父类相同
# super().__init__(name,kind)
# super(Bird,self).__init__(name,kind) #注意 括号前面的元素是子类 当前类 告诉父类
Animal.__init__(self,name,kind) #注意 没有括号
self.eyes_color = eyes_color #自己的属性 自己赋值
def say(self):
print("%s can say like people"%self.name)
laohu = Tiger('老虎','公') # 实参与形参一一对应 即动物的属性此对象都有 也麻烦
print(laohu.walk(),laohu.fly(),laohu.name) # 父类的方法和属性都可以用了 继承
yingwu = Bird('鹦鹉','公','blue') # 最好变量名 有意义 不是 abcd 。。。
print(yingwu.fly(),yingwu.eyes_color,yingwu.say())
多继承
引子:
各种动物,每一种动物都是一个类 青蛙、天鹅、老虎、鹦鹉 青蛙 :走,游泳 天鹅 :走,游泳,飞 老虎 :走,游泳 鹦鹉 :走,飞,说话 class FlyAnimal: def fly(self):pass class SwimAnimal: def swim(self):pass def eat():pass class WalkAnimal: def walk(self):pass def eat():pass class Frog(SwimAnimal,WalkAnimal): pass class Tiger(SwimAnimal,WalkAnimal):pass class Swan(FlyAnimal,SwimAnimal,WalkAnimal):pass class Parrot(FlyAnimal,WalkAnimal): def talk(self): pass
class Frog(SwimAnimal,WalkAnimal): pass
class Tiger(SwimAnimal,WalkAnimal):pass
class Swan(FlyAnimal,SwimAnimal,WalkAnimal):pass
class Parrot(FlyAnimal,WalkAnimal):
def talk(self):
pass
多继承 是python语言中特有的继承方式 java语言中不支持多继承的,C# 也不支持多继承 C++支持多继承 c c++ c# java 多继承和单继承是一样的 如果对象使用名字 是子类中有的,那么一定用子类的 子类没有,可以到多个父类中去寻找 如果多个和父类都有,那么用谁的
如果父类子类都想用,super(),父类名.方法名
算法:
1钻石继承问题
代码实现:
钻石继承问题 class A(object): def func(self): print('a') class B(A): # def func(self): # print('b') class C(A): # def func(self): # print('c') class D(B,C): # def func(self): # print('d') d = D() d.func()
逐个隐藏 函数 来查看调用顺序
# super().func() 左想 class A(object): def func(self): print('a',end='') class B(A): pass def func(self): super().func() print('b',end='') class C(A): pass def func(self): super().func() print('c',end='') class D(B,C): pass def func(self): super().func() print('d',end='') b = B() b.func() print() d = D() d.func() # 在多继承中,super就只和mro顺序有关系,和父类子类没有关系了
2乌龟继承顺序
代码实现:
乌龟继承问题 class A(object): def func(self): print('a') class B(A): pass # def func(self): # print('b') class C(A): pass # def func(self): # print('c') class D(B): pass # def func(self): # print('d') class E(C): pass # def func(self): # print('e') class F(D,E): pass # def func(self): # print('f') f = F() f.func()
过程实现:
# C3算法 # A= [AO] # B = B ,B节点的父类对应的顺序 # B = B ,A节点顺序 # B = B ,[AO] # 提取第一个点 # 如果从左到右第一个类, # 在后面的继承顺序中也是第一个,或者不再出现在后面的继承顺序中 # 那么就可以把这个点提取出来,作为继承顺序中的第一个类 # B = [AO] # BA = [O] # B这个节点的继承顺序 :[BAO] # C = C,[AO] # C = [AO] # CA = [O] # C这个节点的继承顺序 :[CAO] # l(D) = D + [BAO] # D = [BAO] # [DBAO] # l(E) = E + [CAO] # [ECAO] # L[F] = F,[BAO],[ECAO] # [F] = [DBAO],[ECAO] # [FD] = [BAO],[ECAO] # [FDB] = [AO],[ECAO] # [FDB] = [AO],[ECAO] # [FDBE] = [AO],[CAO] # [FDBEC] = [AO],[AO] # [FDBECA] = [O],[O] # [FDBECAO]
广度优先 C3算法 99%的情况都可以用眼睛看出来 但是仍然有1%的情况是看不出来的 C3算法是怎么计算的
C3算法代码实现
class A(object): def func(self): print('a') class B(A): pass def func(self): print('b') class C(A): pass def func(self): print('c') class F: pass def func(self): print('f') class D(A,F): pass # def func(self): # print('d') class E(B,C,F): pass def func(self): print('e') class G(C,D): pass def func(self): print('g') class H(E,G): pass def func(self): print('h') print(H.mro()) # 就是帮助我们来展示c3算法的继承顺序
在python2.7中
主动继承object才是新式类,默认是经典类
# coding:utf-8 # 新式类 继承object # 经典类 只在py2.x中有 默认不继承object # 多继承 # 遵循的是深度优先 class A:pass # def func(self): # print('a') class B(A): pass # def func(self): # print('b') class C(A): pass def func(self): print('c') class D(B,C):pass # def func(self): # print('d') d = D() d.func()
继承总结
单继承
子类有的就用子类的
没有的就用父类的
如果父类子类都想用,super(),父类名.方法名
多继承
新式类 :
继承object
py2 要主动继承object才是新式类,默认是经典类
python2 必须 super(现在类,self) 传给父类(object)
遵循的是广度优先算法,C3算法
有super()的,super遵循mro顺序的
有mro()方法
经典类 :
不继承object
多个类之间去寻找方法的时候遵循深度优先
没有super方法
也没有mro
只在python2 中存在
人狗大战:
继承写法
class Animal(object): def __init__(self,name,blood,ad): self.name = name self.hp = blood self.ad = ad class Dog(Animal): def __init__(self,name,blood,ad,kind): super().__init__(name,blood,ad) self.kind = kind def bite(self,person): person.hp -= self.ad print('%s攻击了%s,%s掉了%s点血' % (self.name, person.name, person.name, self.ad)) class Person(Animal): def __init__(self,name,hp,ad,sex): super().__init__(name,hp,ad) self.sex = sex def fight(self,dog): dog.hp -= self.ad print('%s攻击了%s,%s掉了%s点血'%(self.name,dog.name,dog.name,self.ad)) hei = Dog('小黑',300,20,'哈士奇') alex = Person('alex',20,1,'不详') alex.fight(hei) print(hei.hp) hei.bite(alex) print(alex.hp) # 抽象 # 继承 # 组合 :什么有什么 # 继承 :什么是什么的关系 # 先想描述的对象 # 先写出对象所对应的类 # 发现多个类之间有相同的代码 # 把相同的代码提取出来,搞成一个父类 # 先抽象,再继承 # 对象 -->类 -->基类 # 基类 -继承-> 子类 -实例化-> 对象