¿Qué es una clase de hermanos en Python?

La documentación de Python 2 dice que la función super () “devuelve un objeto proxy que delega las llamadas de método a una clase de tipo padre o hermana”.

Las preguntas:

  1. ¿Qué es una clase de hermanos en Python?
  2. ¿Cómo delegas una llamada de método a una clase de hermanos?

Mi presunción era que un hermano para una clase dada es una clase que hereda del mismo padre. Redacté el siguiente código para ver cómo una llamada a un método puede delegarse a un hermano, pero no funcionó. ¿Qué hago o entiendo mal?

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' 

Después de un poco más de investigación y lectura, el super () de Python se consideró super! Artículo llegué a las siguientes conclusiones:

  1. Una clase de hermanos es lo que estaba pensando que era. Es una clase que hereda del mismo padre. Es la definición de la documentación de Python que me sacó del curso. Parece que cuando la documentación de Python dice que el método de los delegates llama a un padre o a una clase de hermanos , significa a un padre o a un hermano de los padres, que también es una clase base de un hijo determinado . Esa es una herencia de diamantes que debe tener lugar.

  2. super() delega una llamada de método a la clase hermana de un padre basándose automáticamente en MRO (orden de resolución de método).

Aquí hay un caso interesante que encontré al experimentar con la función 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() 

El código se imprimirá

 MethodA of ClassB MethodA of ClassA 

Si usted, como yo, se pregunta por qué el Método A de Class0 nunca se imprime, esta es la explicación tal como la entiendo. El MRO de la ClassC tal como está impreso con la print(ClassC.__mro__) es

(, , , , ) .

Ahora, si sigue la MRO, la función super () del Método A () de ClassC llamará al Método A () de ClassA, que antes de imprimir llamará al Método A () de classB (ya que es el siguiente en MRO). Y el Método A () de ClassB a su vez solo imprimirá y saldrá, ya que no usa la función super () para delegar la llamada al método más arriba en la cadena MRO.

Un hermano es una clase con el mismo padre, como usted sospechaba. El caso que te falta es que super podría llamar a un método de hermanos si esta clase en sí misma se hereda de forma múltiple de :

 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 

En C , llamamos super() , pero obtuvimos B , que es un hermano, no un padre y no el padre de un hermano, sino un hermano directo real de C