2015-01-14 3 views
9

Документация Python 2 гласит, что функция super()«возвращает прокси-объект, который делегирует вызовы методов родительскому или родному классу типа».Что такое класс sibling в Python?

Вопросы:

  1. Что такое класс родственный в Python?
  2. Как вы передаете вызов метода классу родства?

Мое предположение заключалось в том, что родственный брат для данного класса является классом, который наследуется от одного и того же родителя. Я разработал следующий код, чтобы узнать, как вызов метода может быть передан брату, но он не работает. Что мне делать или понимать неправильно?

class ClassA(object): 
    def MethodA(self): 
     print "MethodA of ClassA" 

class ClassB(ClassA): 
    def MethodB(self): 
     print "MethodB of ClassB" 

class ClassC(ClassA): 
    def MethodA(self): 
     super(ClassC, self).MethodA() 

    def MethodB(self): 
     super(ClassC, self).MethodB() 

if __name__ == '__main__': 
    ClassC().MethodA() # Works as expected 

    # Fail while trying to delegate method to a sibling. 
    ClassC().MethodB() # AttirbuteError: 'super' object has no attribute 'MethodB' 
+0

У меня нет времени, чтобы написать полный ответ, но я думаю, что документы относятся к множественному наследованию. Если класс C наследуется как от A, так и от B, вы можете рассматривать A и B как «братья и сестры» в некотором смысле. 'super()' вызовы в теле A на экземпляре C будут делегировать B. См. [этот вопрос] (http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with - множественное наследство) для низкого уровня. –

+1

Принятый ответ на этот вопрос здесь объясняет детали того, как 'super()' действительно может вызывать родительские, но также и родственные классы: http://stackoverflow.com/questions/5033903/python-super-method-and-calling-alternatives –

+0

@SimeonVisser, я видел этот вопрос, даже снял его. Он не дает четкого ответа на вопрос о том, что такое класс братьев и сестер. Этот вопрос связан с этим, но явно не является дубликатом. – golem

ответ

5

После некоторых дальнейших исследований и чтение Python’s super() considered super! статьи, я пришел к следующим выводам:

  1. Класса родственного является то, что я думал, что это было. Это класс, который наследуется от одного и того же родителя. Это определение документации на Python отбросило меня с курса. Похоже, что когда в документации Python говорится, что метод делегатов вызывает родительский или родственный класс, он означает родительскому или родительскому брату, который также является базовым классом данного ребенка. Это наследование бриллиантов должно иметь место.

  2. super() функции делегирует вызов метода в классе родственного родителя автоматически на основе MRO (метод разрешения заказа).

Вот интересный случай, я обнаружил, экспериментируя с super() функции:

class Class0(object): 
    def MethodA(self): 
     print("MethodA of Class0") 

class ClassA(Class0): 
    def MethodA(self): 
     super(ClassA, self).MethodA() 
     print("MethodA of ClassA") 

class ClassB(Class0): 
    def MethodA(self): 
     print("MethodA of ClassB") 

class ClassC(ClassA, ClassB): 
    def MethodA(self): 
     super(ClassC, self).MethodA() 

if __name__ == '__main__': 
    ClassC().MethodA() 

Код напечатает

MethodA of ClassB 
MethodA of ClassA 

Если вы, как мне интересно, почему Methoda из class0 никогда не получает напечатано, вот объяснение, как я его понимаю. MRO класса C, напечатанный print(ClassC.__mro__), составляет

(<class '__main__.ClassC'>, <class '__main__.ClassA'>, <class '__main__.ClassB'>, <class '__main__.Class0'>, <class 'object'>).

Теперь, если вы следуете MRO, функция super() класса MethodA() класса C вызовет метод MethodA() класса A, который перед печатью вызовет MethodA() класса B (поскольку он следующий в MRO). И MethodA() ClassB, в свою очередь, будет просто печатать и выходить, поскольку он не использует функцию super() для делегирования вызова метода дальше по цепочке MRO.

0

Братство - это класс с одним и тем же родителем, как вы подозревали. Случай вы упускаете что super может вызвать метод родственного если сам этот класс будучи многократно унаследован от:

class A(object): 
    def something(self): 
    print("A") 
class B(A): 
    def something(self): 
    print("B") 
class C(A): 
    def something(self): 
    print("C, about to call super()") 
    super(C, self).something() 
class D(C, B): 
    def something(self): 
    super(D, self).something() 

>>> D().something() 
C, about to call super() 
B 

В C, мы назвали super(), но мы получили B - что родной брат, не a parent и не родительский брат, но фактический непосредственный брат C.

+0

Спасибо, я пришел к такому же выводу. Я думаю, что более точным определением будет * родственный родитель, который также является базовым классом данного ребенка * - определение, которое я использовал в своем собственном ответе. – golem

+0

Нет, это не точное определение. 'B' не является родным * родителем *' C'. Это * sibling * of 'C'. – lmm

+0

B является первым родителем, C является вторым родителем. B и C - братья и сестры. В родительском браке, который также является базовым классом данного дочернего *, замените его, и вы получите: брата B, который также является базовым классом D. Это C =). – golem

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