Estoy acostumbrado a que en Objective-C tengo esta construcción:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
¿Python también debería llamar a la implementación de la clase padre __init__
?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
¿Es esto también verdadero / falso para __new__()
y __del__()
?
Editar: Hay una pregunta muy similar: Herencia y anulación __init__
en Python
python
oop
superclass
Georg Schölly
fuente
fuente
object
fue un error tipográfico. Pero ahora ni siquiera tiene elsuper
título de su pregunta se refiere.Respuestas:
En Python, llamar a la superclase '
__init__
es opcional. Si lo llama, también es opcional usar elsuper
identificador o nombrar explícitamente la superclase:En el caso de un objeto, no es estrictamente necesario llamar al súper método, ya que el súper método está vacío. Lo mismo para
__del__
.Por otro lado, para
__new__
, de hecho, debería llamar al supermétodo y usar su retorno como el objeto recién creado, a menos que explícitamente desee devolver algo diferente.fuente
[super init]
, sería más común. Solo un pensamiento especulativo; la súper construcción en Python 2.x es un poco incómoda para mí.Si necesita hacer algo de super
__init__
además de lo que se está haciendo en la clase actual,__init__,
debe llamarlo usted mismo, ya que eso no sucederá automáticamente. Pero si no necesita nada de Super,__init__,
no necesita llamarlo. Ejemplo:__del__
es de la misma manera, (pero tenga cuidado de no confiar en la__del__
finalización; considere hacerlo a través de la declaración with en su lugar).Raramente uso
__new__.
hago toda la inicialización en__init__.
fuente
super(D,self).__init__()
En la respuesta de Anon:
"Si necesita hacer algo de super
__init__
además de lo que se está haciendo en la clase actual__init__
, debe llamarlo usted mismo, ya que eso no sucederá automáticamente"Es increíble: está redactando exactamente lo contrario del principio de herencia.
No es que "algo de super
__init__
(...) no suceda automáticamente" , es que sucedería automáticamente, pero no sucede porque la clase base '__init__
es anulada por la definición de la clase derivada__init__
Entonces, ¿POR QUÉ definir una "clase derivada"
__init__
, ya que anula lo que se pretende cuando alguien recurre a la herencia?Es porque uno necesita definir algo que NO se hace en la clase base '
__init__
, y la única posibilidad de obtener eso es poner su ejecución en una__init__
función de clase derivada' .En otras palabras, uno necesita algo en la clase base '
__init__
además de lo que se haría automáticamente en la clase base'__init__
si este último no fuera anulado.NO al contrario.
Entonces, el problema es que las instrucciones deseadas presentes en la clase base '
__init__
ya no se activan en el momento de la instanciación. Para compensar esta inactivación, se requiere algo especial: llamar explícitamente a la clase base '__init__
, para MANTENER , NO AGREGAR, la inicialización realizada por la clase base'__init__
. Eso es exactamente lo que se dice en el documento oficial:Esa es toda la historia:
cuando el objetivo es MANTENER la inicialización realizada por la clase base, que es pura herencia, no se necesita nada especial, solo se debe evitar definir una
__init__
función en la clase derivadacuando el objetivo es REEMPLAZAR la inicialización realizada por la clase base,
__init__
debe definirse en la clase derivadacuando el objetivo es AGREGAR procesos a la inicialización realizada por la clase base, se
__init__
debe definir una clase derivada que comprenda una llamada explícita a la clase base__init__
Lo que siento asombroso en la publicación de Anon no es solo que él exprese lo contrario de la teoría de la herencia, sino que ha habido 5 tipos pasando por alto sin votar, y además no ha habido nadie que reaccione en 2 años en un hilo cuyo tema interesante debe leerse con relativa frecuencia.
fuente
Editar : (después del cambio de código)
No hay forma de que le digamos si necesita o no llamar a sus padres
__init__
(o cualquier otra función). La herencia obviamente funcionaría sin tal llamado. Todo depende de la lógica de su código: por ejemplo, si todo__init__
se realiza en la clase principal, puede omitir la clase secundaria por__init__
completo.considere el siguiente ejemplo:
fuente
No hay una regla dura y rápida. La documentación de una clase debe indicar si las subclases deben llamar al método de superclase. A veces, desea reemplazar por completo el comportamiento de la superclase y otras veces aumentarlo, es decir, llamar a su propio código antes y / o después de una llamada de la superclase.
Actualización: la misma lógica básica se aplica a cualquier llamada a método. Los constructores a veces necesitan una consideración especial (ya que a menudo establecen un estado que determina el comportamiento) y destructores porque son constructores paralelos (por ejemplo, en la asignación de recursos, por ejemplo, conexiones de bases de datos). Pero lo mismo podría aplicarse, por ejemplo, al
render()
método de un widget.Actualización adicional: ¿Qué es el OPP? ¿Te refieres a OOP? No, una subclase a menudo necesita saber algo sobre el diseño de la superclase. No los detalles de implementación internos, sino el contrato básico que la superclase tiene con sus clientes (usando clases). Esto no viola los principios de OOP de ninguna manera. Es por eso que
protected
es un concepto válido en OOP en general (aunque no, por supuesto, en Python).fuente
OMI, deberías llamarlo. Si su superclase es
object
, no debería, pero en otros casos creo que es excepcional no llamarla. Como ya respondieron otros, es muy conveniente si su clase ni siquiera tiene que anularse__init__
, por ejemplo, cuando no tiene un estado interno (adicional) para inicializar.fuente
Sí, siempre debe llamar a la clase base
__init__
explícitamente como una buena práctica de codificación. Olvidar hacer esto puede causar problemas sutiles o errores de tiempo de ejecución. Esto es cierto incluso si__init__
no toma ningún parámetro. Esto es diferente a otros lenguajes donde el compilador llamaría implícitamente al constructor de la clase base por usted. ¡Python no hace eso!La razón principal para llamar siempre a la clase base
_init__
es que la clase base generalmente puede crear variables miembro e inicializarlas a los valores predeterminados. Entonces, si no llama a la clase base init, ninguno de ese código se ejecutará y terminará con la clase base que no tiene variables miembro.Ejemplo :
Esto imprime ..
Ejecute este código .
fuente