subclases son que privados los instancias ejemplos ejemplo definir clases clase atributos python inheritance multiple-inheritance concept

privados - que son los atributos en python



Python admite una forma limitada de herencia múltiple. ¿En qué forma limitada? (2)

Aparte de la respuesta de @Matt Anderson, creo que las limitaciones son, de hecho, para las clases de estilo antiguo (que aún se abordan en el tutorial de Python 2.6 ).

En el tutorial de Python 3, el texto es ahora: Python también admite una forma de herencia múltiple .

En el tutorial de Python se dice que " Python admite una forma limitada de herencia múltiple ".

¿Cuáles son las limitaciones?


No estoy seguro de a qué limitaciones se refería el autor del tutorial de Python, pero supongo que tiene que ver en parte con la forma en que se implementa la búsqueda de método / atributo en python (el "orden de resolución de método" o MRO). Python utiliza el mecanismo de linealización de la superclase C3 ; esto es para lidiar con lo que se denomina " El problema del diamante ".

Una vez que ha introducido la herencia múltiple en su jerarquía de clases, cualquier clase dada no tiene una única clase potencial de la que hereda, solo tiene "la siguiente clase en el MRO", incluso para las clases que esperan que hereden de alguna clase. clase en particular

Por ejemplo, si la class A(object) , la class B(A) , la class C(A) y la class D(B, C) , entonces el MRO para la clase D es D->B->C->A La clase B podría haber sido escrita, probablemente lo fue, pensando que desciende de A, y cuando se llama super() en sí misma, obtendrá un método para A. Pero esto ya no es cierto; cuando B llama a super() , obtendrá un método en C en su lugar, si existe.

Si cambia las firmas de método en métodos sobrescritos, esto puede ser un problema La clase B, que espera la firma de un método de la clase A cuando llama a super, en lugar de eso, obtiene un método de C, que podría no tener esa firma (y podría o no implementar el comportamiento deseado, desde el punto de vista de la clase B).

class A(object): def __init__(self, foo): print "A!" class B(A): def __init__(self, foo, bar): print "B!" super(B, self).__init__(foo) class C(A): def __init__(self, foo, baaz): print "C!" super(C, self).__init__(foo) class D(B, C): def __init__(self, foo, bar): print "D!" super(D, self).__init__(foo, bar) print D.mro() D("foo", "bar")

En este ejemplo de código, las clases B y C han extendido razonablemente A, y han cambiado sus firmas __init__ , pero llaman a su firma de superclase esperada correctamente. Pero cuando haces D así, la "superclase" efectiva de B se convierte en C en lugar de A. Cuando llama super, las cosas explotan:

[<class ''__main__.D''>, <class ''__main__.B''>, <class ''__main__.C''>, <class ''__main__.A''>, <type ''object''>] D! B! Traceback (most recent call last): File "/tmp/multi_inherit.py", line 22, in <module> D("foo", "bar") File "/tmp/multi_inherit.py", line 19, in __init__ super(D, self).__init__(foo, bar) File "/tmp/multi_inherit.py", line 9, in __init__ super(B, self).__init__(foo) TypeError: __init__() takes exactly 3 arguments (2 given)

Este mismo tipo de cosas podría suceder también con otros métodos (si se llama super() ), y el "diamante" no tiene que aparecer solo en la raíz de la jerarquía de clases.