Je suis utilisé en Objective-C, j'ai cette construction:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
Python devrait-il également appeler l'implémentation de la classe parente pour __init__
?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
Est-ce également vrai / faux pour __new__()
et __del__()
?
Edit: il y a une question très similaire: héritage et remplacement __init__
en Python
python
oop
superclass
Georg Schölly
la source
la source
object
était une faute de frappe. Mais maintenant, vous n'avez même pas lesuper
titre de votre question.Réponses:
En Python, appeler la super-classe '
__init__
est facultatif. Si vous l'appelez, il est alors également facultatif d'utiliser l'super
identifiant ou de nommer explicitement la super classe:En cas d'objet, l'appel de la super méthode n'est pas strictement nécessaire, car la super méthode est vide. Pareil pour
__del__
.D'autre part, pour
__new__
, vous devez en effet appeler la super méthode et utiliser son retour comme objet nouvellement créé - à moins que vous ne souhaitiez explicitement renvoyer quelque chose de différent.la source
[super init]
, ce serait plus courant. Juste une pensée spéculative; la super construction en Python 2.x est un peu gênante pour moi.Si vous avez besoin de faire quelque chose de super
__init__
en plus de ce qui est fait dans la classe actuelle,__init__,
vous devez l'appeler vous-même, car cela ne se produira pas automatiquement. Mais si vous n'avez besoin de rien de super,__init__,
pas besoin de l'appeler. Exemple:__del__
est la même manière, (mais méfiez-vous de vous fier à la__del__
finalisation - envisagez de le faire via l'instruction with à la place).J'utilise rarement
__new__.
je fais toute l'initialisation en__init__.
la source
super(D,self).__init__()
Dans la réponse d'Anon:
"Si vous avez besoin de faire quelque chose de super
__init__
en plus de ce qui est fait dans la classe actuelle__init__
, vous devez l'appeler vous-même, car cela ne se produira pas automatiquement"C'est incroyable: il formule exactement le contraire du principe de l'héritage.
Ce n'est pas que "quelque chose de super
__init__
(...) ne se produira pas automatiquement" , c'est que cela se produira automatiquement, mais cela n'arrivera pas parce que la classe de base '__init__
est remplacée par la définition de la classe dérivée__init__
Alors, POURQUOI définir une classe_ dérivée '
__init__
, puisqu'elle remplace ce qui est visé quand quelqu'un recourt à l'héritage ??C'est parce qu'il faut définir quelque chose qui n'est PAS fait dans la classe de base '
__init__
, et la seule possibilité d'obtenir cela est de mettre son exécution dans une__init__
fonction de classe dérivée' .En d'autres termes, il faut quelque chose dans la classe de base '
__init__
en plus de ce qui serait automatiquement fait dans la classe de base'__init__
si cette dernière n'était pas remplacée.PAS le contraire.
Ensuite, le problème est que les instructions souhaitées présentes dans la classe de base '
__init__
ne sont plus activées au moment de l'instanciation. Afin de compenser cette inactivation, quelque chose de spécial est nécessaire: appeler explicitement la classe de base '__init__
, afin de GARDER , NE PAS AJOUTER, l'initialisation effectuée par la classe de base'__init__
. C'est exactement ce qui est dit dans la doc officielle:C'est toute l'histoire:
lorsque le but est de GARDER l'initialisation effectuée par la classe de base, c'est-à-dire l'héritage pur, rien de spécial n'est nécessaire, il faut juste éviter de définir une
__init__
fonction dans la classe dérivéelorsque le but est de REMPLACER l'initialisation effectuée par la classe de base,
__init__
doit être définie dans la classe dérivéelorsque le but est d'ajouter des processus à l'initialisation effectuée par la classe de base, une classe dérivée '
__init__
doit être définie, comprenant un appel explicite à la classe de base__init__
Ce que je ressens étonnant dans le poste d'Anon, ce n'est pas seulement qu'il exprime le contraire de la théorie de l'héritage, mais qu'il y a eu 5 mecs qui passent par ce vote à la hausse sans tourner les cheveux, et de plus il n'y a eu personne pour réagir en 2 ans en un fil dont le sujet intéressant doit être lu relativement souvent.
la source
Edit : (après le changement de code)
Il n'y a aucun moyen pour nous de vous dire si vous devez ou non appeler vos parents
__init__
(ou toute autre fonction). L'héritage fonctionnerait évidemment sans un tel appel. Tout dépend de la logique de votre code: par exemple, si tout ce que vous__init__
faites est fait dans la classe parente, vous pouvez simplement ignorer__init__
complètement la classe enfant .Prenons l'exemple suivant:
la source
Il n'y a pas de règle absolue. La documentation d'une classe doit indiquer si les sous-classes doivent appeler la méthode de la superclasse. Parfois, vous voulez remplacer complètement le comportement de la superclasse, et à d'autres moments l'augmenter - c'est-à-dire appeler votre propre code avant et / ou après un appel de superclasse.
Mise à jour: la même logique de base s'applique à tout appel de méthode. Les constructeurs ont parfois besoin d'une attention particulière (car ils mettent souvent en place un état qui détermine le comportement) et les destructeurs parce qu'ils sont parallèles aux constructeurs (par exemple dans l'allocation des ressources, par exemple les connexions de base de données). Mais la même chose pourrait s'appliquer, par exemple, à la
render()
méthode d'un widget.Mise à jour supplémentaire: qu'est-ce que l'OPP? Voulez-vous dire POO? Non - une sous-classe a souvent besoin de savoir quelque chose sur la conception de la superclasse. Pas les détails de mise en œuvre interne - mais le contrat de base que la superclasse a avec ses clients (en utilisant des classes). Cela ne viole en aucun cas les principes de la POO. C'est pourquoi
protected
est un concept valide en POO en général (mais pas, bien sûr, en Python).la source
IMO, vous devriez l'appeler. Si votre superclasse l'est
object
, vous ne devriez pas, mais dans d'autres cas, je pense qu'il est exceptionnel de ne pas l'appeler. Comme d'autres l'ont déjà répondu, c'est très pratique si votre classe n'a même pas à se redéfinir__init__
, par exemple lorsqu'elle n'a pas d'état interne (supplémentaire) à initialiser.la source
Oui, vous devez toujours appeler
__init__
explicitement la classe de base comme une bonne pratique de codage. Oublier de le faire peut entraîner des problèmes subtils ou des erreurs d'exécution. Ceci est vrai même si__init__
ne prend aucun paramètre. Ceci est différent des autres langages où le compilateur appellerait implicitement le constructeur de classe de base pour vous. Python ne fait pas ça!La principale raison de toujours appeler la classe de base
_init__
est que la classe de base peut généralement créer des variables membres et les initialiser aux valeurs par défaut. Donc, si vous n'appelez pas la classe de base init, aucun de ce code ne sera exécuté et vous vous retrouverez avec une classe de base qui n'a pas de variables membres.Exemple :
Cela imprime.
Exécutez ce code .
la source