Así que seguí Super Considered Dañino de Python y fui a probar sus ejemplos.
Sin embargo, el Ejemplo 1-3 , que se supone que muestra la forma correcta de llamar supercuando se manejan __init__métodos que esperan diferentes argumentos, no funciona.
Esto es lo que obtengo:
~ $ python example1-3.py
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
File "Download/example1-3.py", line 27, in <module>
E(arg=10)
File "Download/example1-3.py", line 24, in __init__
super(E, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 14, in __init__
super(C, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 4, in __init__
super(A, self).__init__(*args, **kwargs)
File "Download/example1-3.py", line 19, in __init__
super(D, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 9, in __init__
super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters
Parece que en objectsí mismo viola una de las mejores prácticas mencionadas en el documento, que es que los métodos que utilicen superdeben aceptar *argsy **kwargs.
Ahora, obviamente, el Sr. Knight esperaba que sus ejemplos funcionaran, entonces, ¿es esto algo que se cambió en las versiones recientes de Python? Revisé 2.6 y 2.7, y falla en ambos.
Entonces, ¿cuál es la forma correcta de abordar este problema?

object, y se asegura a la llamadaobject'S__init__correctamente.__init__en cuenta que onobjectignora silenciosamente cualquier parámetro en Python 2.5. Esto cambió en Python 2.6.Respuestas:
A veces, dos clases pueden tener algunos nombres de parámetros en común. En ese caso, no puede
**kwargsquitar los pares clave-valor o eliminarlos*args. En su lugar, puede definir unaBaseclase queobject, a diferencia de , absorbe / ignora argumentos:rendimientos
Tenga en cuenta que para que esto funcione,
Basedebe ser la penúltima clase en el MRO.fuente
Basellamarsuper(Base, self).__init__()?Basedebe llegar al final del MRO (exceptoobject). Llamarobject.__init__no hace nada, por lo que está bien no llamarsuper(Base, self).__init__(). De hecho, creo que puede ser más claro no incluirsuper(Base, self).__init__()para llevar a casa el punto queBasees el final de la línea.Si va a tener mucha herencia (ese es el caso aquí), le sugiero que pase todos los parámetros usando
**kwargs, y luegopopinmediatamente después de usarlos (a menos que los necesite en las clases superiores).Esta es la forma más sencilla de resolver ese tipo de problemas.
fuente
Como se explica en super () de Python considerado super , una forma es hacer que la clase se coma los argumentos que requiere y pase el resto. Por lo tanto, cuando la cadena de llamadas llega
object, todos los argumentos se han comido yobject.__init__se llamarán sin argumentos (como se espera). Entonces su código debería verse así:fuente
E(arg = 10)? No me gusta este método, necesito conocer el MRO de antemano para poder usarlo. El otro método en el que escribo una "clase raíz" que heredaobjectparece mucho más limpio.super, por lo que este enfoque podría ser bastante teórico.