Python2.7和3的多重继承区别
Multiple inheritance difference between Python 2.7 and 3
我已经了解到 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')
在Python3.,我得到:
{'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 中解决此问题的任何解决方案?
在你的继承树底部使用一个哨兵对象不调用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 (or the PyCon presentation based on it)。
我已经了解到 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')
在Python3.,我得到:
{'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 中解决此问题的任何解决方案?
在你的继承树底部使用一个哨兵对象不调用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 (or the PyCon presentation based on it)。