python 有关super

本文通过实例详细解析了Python中多重继承的实现方式及其注意事项,包括如何正确使用super()调用父类构造函数,以及方法解析顺序(MRO)对继承的影响。
# coding=utf-8_
_author__ = "leaves"

print '--------------1------------------'


class Base1(object):  # 这里必须有object否则子类调用super会报错,因为Python 2中的classobj不算做一种type,Python 3的话应该就没有这种问题
    def __init__(self):
        print 'Enter Base1 init'
        print 'Enter Base1 init'


class Child1(Base1):
    def __init__(self):
        print "Enter Child1 init"
        Base1.__init__(self)
        print "Exit Child1 init"


child = Child1()
print '--------------2------------------'


class Base2(object):
    def __init__(self):
        print 'Enter Base2 init'
        print 'Enter Base2 init'


class Child2(Base2):
    def __init__(self):
        print "Enter Child2 init"
        super(Child2, self).__init__()
        print "Exit Child2 init"


child = Child2()
print '--------------3------------------'
# Base2继承自Base1,这样就两个init都可以执行了



class Child3(Base2, Base1):
    def __init__(self):
        print "Enter Child3 init"
        # 这里super只执行了Base2的init,两个父类有相同的方法名或变量名时,无法确定应继承哪一个,,Python会自动按顺序选择拥有所需方法名的第一个父类并执行,而忽略其他父类中的同名方法
        super(Child3, self).__init__()
        print "Exit Child3 init"


child = Child3()
print '--------------4------------------'
# Base2继承自Base1,这样就两个init都可以执行了
class Base3(Base1):
    def __init__(self):
        print 'Enter Base3 init'
        super(Base3, self).__init__()
        print 'Enter Base3 init'


class Child4(Base3):
    def __init__(self):
        print "Enter Child3 init"
        # 这里super只执行了Base2的init,两个父类有相同的方法名或变量名时,无法确定应继承哪一个,,Python会自动按顺序选择拥有所需方法名的第一个父类并执行,而忽略其他父类中的同名方法
        super(Child4, self).__init__()
        print "Exit Child3 init"


child = Child4()
print '--------------5------------------'


class Base4(object):
    def __init__(self):
        print 'Enter Base4 init'
        print 'Enter Base4 init'


class Child5(Base4):
    def __init__(self):
        print 'Enter Child5 init'
        Base4.__init__(self)
        print 'Enter Child5 init'


class Child6(Base4):
    def __init__(self):
        print 'Enter Child6 init'
        Base4.__init__(self)
        print 'Enter Child6 init'


class Child7(Child5, Child6):
    def __init__(self):
        print 'Enter Child7 init'
        Child5.__init__(self)
        Child6.__init__(self)
        print 'Enter Child7 init'


child = Child7()
print '--------------6------------------'


class Base5(object):
    def __init__(self):
        print 'Enter Base4 init'
        print 'Enter Base4 init'


class Child8(Base5):
    def __init__(self):
        print 'Enter Child5 init'
        super(Child8, self).__init__()
        print 'Enter Child5 init'


class Child9(Base4):
    def __init__(self):
        print 'Enter Child6 init'
        super(Child9, self).__init__()
        print 'Enter Child6 init'


class Child10(Child5, Child6):
    def __init__(self):
        print 'Enter Child7 init'
        super(Child10, self).__init__()
        print 'Enter Child7 init'


child = Child10()


outPut:

--------------1------------------
Enter Child1 init
Enter Base1 init
Enter Base1 init
Exit Child1 init
--------------2------------------
Enter Child2 init
Enter Base2 init
Enter Base2 init
Exit Child2 init
--------------3------------------
Enter Child3 init
Enter Base2 init
Enter Base2 init
Exit Child3 init
--------------4------------------
Enter Child3 init
Enter Base3 init
Enter Base1 init
Enter Base1 init
Enter Base3 init
Exit Child3 init
--------------5------------------<<span style="color:#ff0000;">基类Base4执行了两次></span>
Enter Child7 init
Enter Child5 init
Enter Base4 init
Enter Base4 init
Enter Child5 init
Enter Child6 init
Enter Base4 init
Enter Base4 init
Enter Child6 init
Enter Child7 init
--------------6------------------
Enter Child7 init
Enter Child5 init
Enter Base4 init
Enter Base4 init
Enter Child5 init
Enter Child7 init


### 使用方法 在 Python 中,`super()` 主要用于调用父类的方法,避免直接使用父类名调用方法带来的一些问题,如修改父类名称时需要多处修改、多继承时代码累赘等问题[^3]。 #### 常用具体语法形式 - **Python 3 中**:`super()` ,它是 `super(type, obj)` 的简化形式,`type` 是当前类,`obj` 是当前实例对象,在类的方法中可以直接使用 `super()` 来调用父类的方法。例如: ```python class Base: def __init__(self): print('Base.__init__') class A(Base): def __init__(self): super().__init__() print('A.__init__') class B(Base): def __init__(self): super().__init__() print('B.__init__') class C(A, B): def __init__(self): super().__init__() print('C.__init__') C() ``` - **Python 2 中**:`super(type, obj)` ,需要显式指定当前类和实例对象。例如: ```python class FooParent(object): def bar(self, message): print(message) class FooChild(FooParent): def bar(self, message): super(FooChild, self).bar(message) FooChild().bar("Hello, Python.") ``` ### 原理 `super()` 的工作原理基于方法解析顺序(MRO,Method Resolution Order)。MRO 是 Python 中用于确定在多继承情况下调用方法的顺序的算法。Python 使用 C3 线性化算法来计算 MRO,它保证了每个类只被访问一次,并且遵循子类优先于父类、从左到右的原则。 当调用 `super()` 时,它会根据 MRO 列表找到下一个类,并调用该类的相应方法。在多继承的情况下,`super()` 会按照 MRO 列表依次调用父类的方法,而不是只调用直接父类的方法。例如在上述 `C` 类的例子中,`C` 的 MRO 列表为 `[C, A, B, Base, object]`,当在 `C` 的 `__init__` 方法中调用 `super().__init__()` 时,会按照 MRO 列表依次调用 `A`、`B`、`Base` 的 `__init__` 方法。 ### 注意事项 - 避免写 `super(self.__class__, self)` ,在某些情况下可能会导致无限递归调用。 - 避免把通过类名调用和 `super` 调用进行混合使用,以免造成混淆和意外的结果。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值