标签:帮助 问题 ret string 而不是 padding base plain call
最近有同学问我关于Python类中的super()和__init__()共同点和不同点的问题, 我今天把它们两个的异同点总结了一下,希望可以帮助遇到同样困惑的同学。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | classBase(object):    def__init__(self):        print‘Base create‘classchildA(Base):    def__init__(self):        print‘creat A ‘,        Base.__init__(self)classchildB(Base):    def__init__(self):        print‘creat B ‘,        super(childB, self).__init__()base =Base()a =childA()b =childB() | 
输出结果:
| 1 2 3 | Base createcreat A  Base createcreat B  Base create | 
区别是使用super()继承时不用显式引用基类。
把基类改为旧式类,即不继承任何基类
| 1 2 3 | classBase():    def__init__(self):        print‘Base create‘ | 
执行时,在初始化b时就会报错:
| 1 2 | super(childB, self).__init__()TypeError: must be type, not classobj | 
在多重继承时会涉及继承顺序,super()相当于返回继承顺序的下一个类,而不是父类,类似于这样的功能:
| 1 2 3 | defsuper(class_name, self):    mro =self.__class__.mro()    returnmro[mro.index(class_name) +1] | 
mro()用来获得类的继承顺序。 例如:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | classBase(object):    def__init__(self):        print‘Base create‘classchildA(Base):    def__init__(self):        print‘enter A ‘        # Base.__init__(self)        super(childA, self).__init__()        print‘leave A‘classchildB(Base):    def__init__(self):        print‘enter B ‘        # Base.__init__(self)        super(childB, self).__init__()        print‘leave B‘classchildC(childA, childB):    passc =childC()printc.__class__.__mro__ | 
输出结果如下:
| 1 2 3 4 5 6 | enter A enter B Base createleave Bleave A(<class ‘__main__.childC‘>, <class ‘__main__.childA‘>, <class ‘__main__.childB‘>, <class ‘__main__.Base‘>, <type‘object‘>) | 
supder和父类没有关联,因此执行顺序是A —> B—>—>Base
执行过程相当于:初始化childC()时,先会去调用childA的构造方法中的 super(childA, self).__init__(), super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().__init__(),这样顺序执行下去。
在多重继承里,如果把childA()中的 super(childA, self).__init__() 换成Base._init_(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB:
| 1 2 3 4 | enter A Base createleave A(<class ‘__main__.childC‘>, <class ‘__main__.childA‘>, <class ‘__main__.childB‘>, <class ‘__main__.Base‘>, <type‘object‘>) | 
从super()方法可以看出,super()的第一个参数可以是继承链中任意一个类的名字,
如果是本身就会依次继承下一个类;
如果是继承链里之前的类便会无限递归下去;
如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;
比如将childA()中的super改为:super(childC, self).__init__(),程序就会无限递归下去。 如:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |   File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()  File "test.py", line 12, in__init__    super(childC, self).__init__()RuntimeError: maximum recursion depth exceeded whilecalling a Python object | 
如果childA基础Base, childB继承childA和Base,如果childB需要调用Base的__init__()方法时,就会导致__init__()被执行两次:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | classBase(object):    def__init__(self):        print‘Base create‘classchildA(Base):    def__init__(self):        print‘enter A ‘        Base.__init__(self)        print‘leave A‘classchildB(childA, Base):    def__init__(self):        childA.__init__(self)        Base.__init__(self)b =childB() | 
Base的__init__()方法被执行了两次
| 1 2 3 4 | enter A Base createleave ABase create | 
使用super()是可避免重复调用
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | classBase(object):    def__init__(self):        print‘Base create‘classchildA(Base):    def__init__(self):        print‘enter A ‘        super(childA, self).__init__()        print‘leave A‘classchildB(childA, Base):    def__init__(self):        super(childB, self).__init__()b =childB()printb.__class__.mro()enter A Base createleave A[<class‘__main__.childB‘>, <class‘__main__.childA‘>, <class‘__main__.Base‘>, <type‘object‘>]
 | 
标签:帮助 问题 ret string 而不是 padding base plain call
原文地址:http://www.cnblogs.com/paranoia/p/6165300.html