【问题标题】:Multiple inheritance difference between Python 2.7 and 3Python 2.7 和 3 的多重继承区别
【发布时间】:2015-06-02 15:03:56
【问题描述】:

我已经知道 Python 2.7 和 3 之间存在差异。实现多重继承,例如:

在 Python 3 中:

class A:
    def __init__(self, x2='', x3='', **kwargs):
        print kwargs
        super().__init__(**kwargs)
        self.x2 = x2
        self.x3 = x3

class B:
    def __init__(self, x4='', x5='', **kwargs):
        print kwargs
        super().__init__(**kwargs)
        self.x4 = x4
        self.x5 = x5

class C(A, B):
    def __init__(self, x1='', **kwargs):
        print kwargs
        super().__init__(**kwargs)
        self.x1 = x1

在 Python 2.7 中:

class A(object):
    def __init__(self, x2='', x3='', **kwargs):
        print kwargs
        super(A, self).__init__(**kwargs)
        self.x2 = x2
        self.x3 = x3

class B(object):
    def __init__(self, x4='', x5='', **kwargs):
        print kwargs
        super(B, self).__init__(**kwargs)
        self.x4 = x4
        self.x5 = x5

class C(A, B):
    def __init__(self, x1='', **kwargs):
        print kwargs
        super(C, self).__init__(**kwargs)
        self.x1 = x1

运行代码:

C(x1='a',x2='b',x3='c',x4='d',x5='e',x6='f',x7='g')

在 Python 3. 中,我得到了:

{'x2': 'b', 'x3': 'c', 'x6': 'f', 'x7': 'g', 'x4': 'd', 'x5': 'e'}
{'x6': 'f', 'x7': 'g', 'x4': 'd', 'x5': 'e'}
{'x6': 'f', 'x7': 'g'}

但是这样做,Python 2.76 也会导致错误:

{'x2': 'b', 'x3': 'c', 'x6': 'f', 'x7': 'g', 'x4': 'd', 'x5': 'e'}
{'x6': 'f', 'x7': 'g', 'x4': 'd', 'x5': 'e'}
{'x6': 'f', 'x7': 'g'}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
super(C, self).__init__(**kwargs)
super(A, self).__init__(**kwargs)
super(B, self).__init__(**kwargs)
TypeError: object.__init__() takes no parameters

我注意到如果我从 Python 2.7 代码中删除 super(B, self).__init__(**kwargs),就不会出现任何错误,因为 class B 可能不会继承自 class A。有人知道这在 Python 3 中是如何工作的吗?以及在 Python 2.7 中解决此问题的任何解决方案?

【问题讨论】:

    标签: python python-2.7 python-3.x multiple-inheritance


    【解决方案1】:

    使用继承树底部的哨兵对象调用super().__init__()

    class Sentinel(object):
        def __init__(self, **kw):
            pass
    
    class A(Sentinel):
        def __init__(self, x2='', x3='', **kwargs):
            super(A, self).__init__(**kwargs)
            self.x2 = x2
            self.x3 = x3
    
    class B(Sentinel):
        def __init__(self, x4='', x5='', **kwargs):
            super(B, self).__init__(**kwargs)
            self.x4 = x4
            self.x5 = x5
    
    class C(A, B):
        def __init__(self, x1='', **kwargs):
            super(C, self).__init__(**kwargs)
            self.x1 = x1
    

    这样Sentinel.__init__ 总是最后调用而不是object.__init__。这样可以确保您的所有 __init__ 方法始终接受相同的参数。

    Raymond Hettinger's super() considered super! article(或PyCon presentation based on it)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-01
      • 2013-09-19
      • 1970-01-01
      • 2013-06-13
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多