面向对象三大特性之二:继承 (Inheritance)
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。
1.0.1 继承写法
class Grandfather: def dance(self): pass class Father(Grandfather): #父类,或 基类 def football(self): pass def basketball(self): pass def somking(self): pass def drinking(self): pass def haircare(self): pass class Son(Father): #子类,或,派生类 def reading(self): pass obj = Son() obj.football()
最简单的练习题:
class F: def f1(self): print('F.f1') def f2(self): print('F.f2') class S(F): def s1(self): print('S.s1') obj = S() obj.s1() obj.f2()
1.0.2 继承重写:
如果 不想用父类里面的方法就可以把父类里面的方法,重新写一个。
执行的时候,就不会去找父类的方法了。
class F: def f1(self): print('F.f1') def f2(self): print('F.f2') class S(F): def s1(self): print('S.s1') def f2(self): #父类方法重写 print('S.f2') obj = S() obj.s1() #s1中的self是形参,此时代指obj obj.f2() #self永远指调用方法的调用者,就是obj
如果我们又想执行父类里面的方法,这里有二个方法:一个是super(),一个就是直接父类类名调用方法
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
super语法 :
super(type[, object-or-type])
type:子类名
bject-or-type:就是self
class F: def f1(self): print('F.f1') def f2(self): print('F.f2') class S(F): def s1(self): print('S.s1') def f2(self): super(S,self).f2() #找父类,然后执行父类的f2方法 F.f2(self) #也可以这样执行父类被重写的方法 print('S.f2')
super().xxx;super(child,self).xxx
方法法1:super(子类,self).父类中的方法(arg)
方法法2:父类名.父类中的方法(self. arg)
class FooParent(object): def __init__(self): self.parent = 'I\'m the parent.' print ('Parent') def bar(self,message): print ("%s from Parent" % message) class FooChild(FooParent): def __init__(self): # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象 super(FooChild,self).__init__() print ('Child') def bar(self,message): super(FooChild, self).bar(message) print ('Child bar fuction') print (self.parent) if __name__ == '__main__': fooChild = FooChild() fooChild.bar('HelloWorld')
1.0.3 多继承:python与c++支持多继续,其他语言不支持。
因为这里面有一个问题,如果两个父类同时用一个方法名定义了不同的方法,那子类在运行的时候,会发生冲突。
所以其他语言都 不支持多继续,但是python可以支持
1.0.3.1 左侧优先:python子类搜索的时候,就从左边的父类开始找,如果找到了,就不继续了。
class F1: def a(self): print('F1.a') class F2: def a(self): print('F2.a') class S(F1,F2): pass obj = S() obj.a()
1.0.3.2 一条道走到黑:
如果子类还有爷爷类,继续爷爷类找,左边第一个父类单线找完了,才会找第二个父类找。
class F0: def a(self): print('F0.a') class F1(F0): def a1(self): print('F1.a') class F2: def a(self): print('F2.a') class S(F1,F2): pass obj = S() obj.a()
1.0.3.3 同一个根,根最后执行:
如果子类的父类拥有相当的祖爷类,左边第一个父类单线找完了,共同祖爷类不会找,程序又会从第二个父开找
class Basic: def a(self): print('F0.a') class F0(Basic): def a0(self): print('F0.a') class F1(F0): def a1(self): print('F1.a') class F2(Basic): def a(self): print('F2.a') class S(F1,F2): pass obj = S() obj.a()
1.0.4 代码执行流程:
class BassRequest(): pass class RequestHandler(BassRequest): def serve_forever(self): #self,是obj print('RequestHandler.server_forever') self.process_request() #这句是Son(),会按继承的规则,去Minx去执行,一定在记住!!! def process_request(self): print('RequestHandler.process_request') class Minx: def process_request(self): print('minx.process_request') class Son(Minx,RequestHandler): pass obj = Son() obj.serve_forever()
#执行结果:
RequestHandler.server_forever
minx.process_request
1.0.5 代码执行流程:
如果在子类中需要父类的构造方法就需要显式地调用父类的构造方法,或者不重写父类的构造方法。
子类不重写 __init__,实例化子类时,会自动调用父类定义的 __init__。
class BassRequest: def __init__(self): print('BassRequest.init') class RequestHandler(BassRequest): def __init__(self): print('RequestHandler.init') super(RequestHandler,self).__init__() BassRequest.__init__(self) def serve_forever(self): #self,是obj print('RequestHandler.server_forever') self.process_request() #这句是Son(),会按继承的规则,去Minx去执行,一定在记住!!! def process_request(self): print('RequestHandler.process_request') class Minx: def process_request(self): print('minx.process_request') class Son(Minx,RequestHandler): pass obj = Son() #执行结果: RequestHandler.init BassRequest.init BassRequest.init
怎么看代码流程:
记住self是谁的对象。出现self就从头开始找
class BassRequest: def __init__(self): #第3步 print('BassRequest.init') class RequestHandler(BassRequest): def __init__(self): #第2步 print('RequestHandler.init') super(RequestHandler,self).__init__() BassRequest.__init__(self) def serve_forever(self): #第5步 #self,是obj print('RequestHandler.server_forever') self.process_request() #这句是Son(),会按继承的规则,去Minx去执行,一定在记住!!! def process_request(self): print('RequestHandler.process_request') class Minx: def process_request(self): #第6步 print('minx.process_request') class Son(Minx,RequestHandler): pass obj = Son() #第1步 obj.serve_forever() #第4步