2015-06-02 1 views
0

У меня уже есть, что есть разница между Python 2.7 и 3. реализации множественного наследования, например:Multiple разница наследования между 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 

Я заметил, если удалить super(B, self).__init__(**kwargs) из Python 2.7 кода, ошибки не будет, поскольку, возможно, class B не наследует от class A. Кто-нибудь знает, как эта работа без проблем в Python 3? и любое решение, разрешающее эту проблему в Python 2.7?

ответ

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).

+0

Большое спасибо! Он работает сейчас! :) –