2016-02-10 3 views
1

Пожалуйста, объясните мне следующее. Если я выполнить это:Метод доступа второго базового класса с супер()

class Base1: 
    def foo(self): 
     print('in Base1.foo') 

b1 = Base1() 
b1.foo() 


class Base2: 
    def foo(self): 
     print('in Base2.foo') 

b2 = Base2() 
b2.foo() 

class Child1(Base1, Base2): 
    def foo(self): 
     super(Child1,self).foo() 

c1 = Child1() 
c1.foo() 

class Child2(Base1, Base2): 
    def foo(self): 
     super(Base1,self).foo() 

c2 = Child2() 
c2.foo() 

я получаю это:

in Base1.foo 
in Base2.foo 
in Base1.foo 
in Base2.foo 

Я понимаю, первые три строки вывода. Но почему я должен дать имя первого базового класса super(), чтобы получить метод второго базового класса?

ответ

4

Вы уклоняетесь от Method Resolution Order, или MRO. Иерархии наследования класса Python: , линеаризованный, с учетом определенного порядка, согласно системе, называемой C3 linearisation.

super() использует этот заказ, чтобы найти следующий атрибут (включая методы) в этом заказе. Учитывая текущий экземпляр и класс, он будет искать порядок для атрибута за данного класса. Для классов Child* MRO сначала перечисляет класс Child*, а затем Base1 и Base2. В последнем примере вы сказали super(), чтобы посмотреть, что MRO начинается со следующего класса после Base1, так что только Base2.foo() еще не найден.

Вы можете задать любой класс для его MRO вызова class.mro() method:

>>> Child2.mro() 
[<class '__main__.Child2'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>] 

super() может быть использован вне методы тоже; вы можете легко увидеть, что происходит, когда вы выбираете различные отправные точки для поиска:

>>> super(Child2, Child2()).foo 
<bound method Base1.foo of <__main__.Child2 object at 0x10f40ff98>> 
>>> super(Base1, Child2()).foo 
<bound method Base2.foo of <__main__.Child2 object at 0x10f40ffd0>> 
>>> super(Base2, Child2()).foo 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'super' object has no attribute 'foo' 
+0

Я был осведомлен о порядке разрешения на метод, но я не знаю, что супер() получают «следующий» базовый класс в линии ... спасибо – steffen

Смежные вопросы