一 : 初识继承
继承是为了在在一个类中方便的使用另一个类中的内容.
class Animal: breath = '呼吸' def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age def eat(self): print(self) print('动物需要进食....') class Person(Animal): pass
这段代码中,类Person继承了类Animal,那么我们把类Person称作子类/派生类,把类Animal称作父类/基类/超类. 在python3.x中,所有类默认继承了objec类,如果在定义类的时候不写括号或者括号内没有内容,默认继承objec类.
子类可以直接使用父类中的内容,比如这个Person类,其中什么都没有,但是在它实例化的时候,会调用父类中的__init__()函数,必须要传入name/sex/age三个参数
p1 = Person('alex', 'laddyboy', 1000)
print(p1.__dict__) # {'name': 'alex', 'sex': 'laddyboy', 'age': 1000}
p1.eat() #<__main__.Person object at 0x0000022FAC4A5390> 动物需要进食....
print(p1.breath) # 呼吸
print(p1) # <__main__.Person object at 0x00000195C7FEB390>
可以看到,当我们调用父类的eat方法,打印self的结果是子类的对象,和打印p1的地址一致,可以通过子类的对象获得父类中的内容.这是因为子类中存在一个指向父类的指针,当调用子类的内容的时候,如果不存在,就会通过这个指针向父类中寻找.原理与类和对象空间的关系相似.
可以直接在子类中调用父类中的内容,可以通过两种方法办到,其一是直接用父类名 . 变量名/方法名 的方式,其二是 用 super() . 变量名/方法名 的方式,推荐用第二种方法,因为python是支持多继承的,这种方法泛用性更高.
class Animal: def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age def eat(self, a1): print('%s吃%s' % (self.name, a1)) def drink(self): print('%s喝东西' % (self.name)) class Cat(Animal): def miaow(self): print('喵喵叫') def drink(self): # 只执行自己类中的方法 print('类Cat中的drink') class Brid(Animal): def __init__(self, name, sex, age, wing): # Animal.__init__(self, name, sex, age) 这是第一种方法 super().__init__(name, sex, age) # 第二种方法(推荐) super(Brid,self).__init__(name,sex,age)这是完整版的调用方式,括号里的父类名和self是可以省略的 self.wing = wing def bark(self): print('嗷嗷叫') def eat(self, argv): super().eat(argv) print('鸟吃虫子...') c1 = Cat('LiFuGui', '雄性', 2) #实例化一只猫 c1.drink() # 调用dring()方法, 此时子类和父类中都有名为dring的方法 打印结果 : 类Cat中的drink c1.eat('耗子') # 子类中没有eat方法,于是调用父类中的eat方法 打印结果:LiFuGui吃耗子
二 : 多继承
一条线的继承很好理解,父类中没有的内容会向父类的父类中寻找,代码如下
class A: def func(self): print('IN A') class B(A): pass # def func(self): # print('IN B') class C(B): pass c1= C() c1.func() # IN A
麻烦的是一个类同时有多个父类:
class A: def func(self): print('IN A') class B(A): pass # def func(self): # print('IN B') class C(A): pass # def func(self): # print('IN C') class D(B): pass # def func(self): # print('IN D') class E(C): pass # def func(self): # print('IN E') class F(D,E): pass # def func(self): # print('IN F') f1 = F() f1.func()
通过mro函数可以获得一个类的继承路线,当它向父类寻找一个内容的时候,会遵循这个顺序
print(F.mro()) #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
这个顺序是通过C3算法得到的,我们不通过mro()函数,可以通过merge list和拓扑排序两种方式获得这个顺序.因为这两种方式太复杂,再次不再描述.