继承 多态现象:一个子类型在任何需要父类型的场合可以被替换成父类型, 即对象可以被视作是父类的实例。 被继承的类被称为“基本类”或“超类”、“父类”。继承的类被称为“导出类”或“子类”。 例: # 父类 class Member(object): def __init__(self, name, age): self.name = name self.age = age print('(Initialized Member: %s)' % self.name) def tell(self): print('Member Name:"%s" Age:"%s"' % (self.name, self.age)) def tell2(self): print('Member haha...') # 子类 class Student(Member): # 继承的父类写括号里面;多继承则写多个,这括号的称为继承元组;多继承时,优先继承出现在继承元组前面的父类的属性及方法 def __init__(self, name, age, marks): Member.__init__(self, name, age) # 父类的初始化,需手动写;自定义constructor后,Python不会自动调用父类的constructor; 不定义constructor的话就会自动调用父类的 #super(Student, self).__init__(name, age) # 这一句跟上面一句效果一样,前提是父类 Member 必须继承 object,如果父类 Member 不继承 object 则报错,如: “class Member:” self.marks = marks print('(Initialized Student: %s)' % self.name) def tell(self): Member.tell(self) # 调用父类的方法,注意:方法调用之前要加上父类名称前缀, 然后把self变量及其他参数传递给它。 print('Marks: "%d"' % self.marks) s = Student('Swaroop', 22, 75) s.tell() # 会调用子类的方法 s.tell2() # 子类没有的, 则使用父类的;如果多继承,且父类都有这个方法,则使用继承元组中排前面的 多继承 概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。 py 2.x 经典类(旧式类): class P1: def foo(self):print('p1-foo') class P2: def foo(self):print('p2-foo') def bar(self):print('p2-bar') class C1(P1,P2): pass class C2(P1,P2): def bar(self):print('c2-bar') class D(C1,C2): pass d=D() d.foo() # 输出 p1-foo d.bar() # 输出 p2-bar #实例d调用foo()时,搜索顺序是 D => C1 => P1 #实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2 #换句话说,经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。 新式类: class P1(object): def foo(self):print('p1-foo') class P2(object): def foo(self):print('p2-foo') def bar(self):print('p2-bar') class C1 (P1,P2): pass class C2 (P1,P2): def bar(self):print('c2-bar') class D(C1,C2): pass d=D() d.foo() # 输出 p1-foo d.bar() # 输出 c2-bar #实例d调用foo()时,搜索顺序是 D => C1 => C2 => P1 #实例d调用bar()时,搜索顺序是 D => C1 => C2 #可以看出,新式类的搜索方式是采用“广度优先”的方式去查找属性。 #Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用(仅新式类有) print(P1.__mro__) # 打印:(<class '__main__.P1'>, <type 'object'>) print(P1.mro()) # 打印:[<class '__main__.P1'>, <type 'object'>] print(C1.__mro__) # 打印:(<class '__main__.C1'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>) print(D.__mro__) # 打印:(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>) 经典类(旧式类) 与 新式类 py2.x 定义类时继承 object 的类称为新式类。没有继承 object 的为旧式类。 py3.x 默认就是新式类。 MRO 即 method resolution order,用于判断子类调用的属性来自于哪个父类。 在Python2.3之前,MRO是基于深度优先算法的(旧式类),自2.3开始使用C3算法(广度优先,新式类)。 C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。 本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。 单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。 super 从 mro 就能知道, super 指的是 MRO 中的下一个类,而不是父类。 super 所做的事如下面代码所示: def super(cls, inst): mro = inst.__class__.mro() return mro[mro.index(cls) + 1] 对于在子类中调用父类方法,要么直接使用父类名来调用方法,要么在子类中用 super ,保持一致,最好不要混用。

浙公网安备 33010602011771号