que veo por todas partes ejemplos de que los métodos de la clase súper deben ser llamados por:Python súper método y piden alternativas
super(SuperClass, instance).method(args)
¿Hay alguna desventaja a hacer:
SuperClass.method(instance, args)
que veo por todas partes ejemplos de que los métodos de la clase súper deben ser llamados por:Python súper método y piden alternativas
super(SuperClass, instance).method(args)
¿Hay alguna desventaja a hacer:
SuperClass.method(instance, args)
considere la siguiente situación:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
# super(B,self).__init__()
A.__init__(self)
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo=D()
Así las clases forman un llamado diamante herencia:
A
/\
B C
\/
D
Ejecución de los rendimientos del código
Running D.__init__
Running B.__init__
Running A.__init__
Eso es malo porque C
' s __init__
se omite. La razón de esto es porque B
's __init__
llama A
' s __init__
directamente.
El propósito de super
es resolver los diamantes de herencia. Si no-comentar
# super(B,self).__init__()
y comentar de salida
A.__init__(self)
el código produce el resultado más deseable:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
Ahora todos los métodos __init__
ser llamado.Tenga en cuenta que en el momento de definir B.__init__
puede pensar que super(B,self).__init__()
es lo mismo que llamar al A.__init__(self)
, pero estaría equivocado. En la situación anterior, super(B,self).__init__()
realmente llama al C.__init__(self)
.
santo fuma, B
sabe nada acerca de C
, y sin embargo super(B,self)
sabe llamar C
's __init__
? La razón es porque self.__class__.mro()
contiene C
. En otras palabras, self
(o en lo anterior, foo
) conoce aproximadamente C
.
Ten cuidado, los dos no son fungibles. Pueden arrojar resultados muy diferentes.
Usando super
has pitfalls. Se necesita un nivel considerable de coordinación entre todas las clases en el diagrama de herencia. (Deben, por ejemplo, o bien tienen la misma firma llamado a __init__
, ya que cualquier particular, __init__
no sabría qué otra __init__
super
podría llamar al lado, o demás use **kwargs
.) Por otra parte, debe ser coherente sobre el uso de super
todas partes. Omita una vez (como en el ejemplo anterior) y vence el objetivo completo de super
. Vea el enlace para ver más trampas.
Si tiene control total sobre la jerarquía de su clase, o evita los diamantes de herencia, entonces no hay necesidad de super
.
No hay penalidad en que está , aunque tu ejemplo es un tanto equivocado. En el primer ejemplo, debe ser
super(SubClass, instance).method(args) # Sub, not SuperClass
y que me lleva a citar el Python docs:
Hay dos casos de uso típicos para
super
. En una jerarquía de clases con herencia simple, se puede usarsuper
para referirse a las clases principales sin nombrarlas explícitamente, lo que hace que el código sea más fácil de mantener. Este uso es muy similar al uso desuper
en otros lenguajes de programación.El segundo caso de uso es para admitir herencia múltiple cooperativa en un entorno de ejecución dinámica. Este caso de uso es exclusivo de Python y no se encuentra en los lenguajes compilados estáticamente o en los idiomas que solo admiten herencia simple. Esto hace posible implementar "diagramas de diamantes" donde múltiples clases base implementan el mismo método. Un buen diseño exige que este método tenga la misma firma de llamada en cada caso (porque el orden de las llamadas se determina en tiempo de ejecución, porque ese orden se adapta a los cambios en la jerarquía de clases, y porque esa orden puede incluir clases hermanas desconocidas antes del tiempo de ejecución)
Básicamente, al usar el primer método, no es necesario codificar su clase primaria para las jerarquías de clase única, y simplemente no puede hacer lo que quiere (eficiente/efectivamente) utilizando el segundo método cuando se usa herencia múltiple.
¿Lo entiendo bien, no hay contras de usar 'super' en situaciones de herencia única? – Wolf
+1 para el enlace super-dañino. Estaba a punto de publicarlo yo mismo. –
thnx, has aclarado mi concepto erróneo. – 0xc0de
[Python's super() considerado super!] (Http://rhettinger.wordpress.com/2011/05/26/super-considered-super/) muestra por qué y cómo usar 'super()'. Por cierto, con las clases de nuevo estilo y la herencia múltiple, siempre hay un diamante de herencia debido al padre 'objeto' común. – jfs