186 votes

Pourquoi aren ' t Python ' méthodes de __init__ superclasse s automatiquement appelées ?

Pourquoi les concepteurs de Python qui décident des sous-classes méthodes n’appellent pas automatiquement les méthodes leur superclasses, comme dans d’autres langues ? Est le Pythonic et recommandé l’idiome vraiment semblable à la suivante ?

186voto

Alex Martelli Points 330805

La distinction cruciale entre Python __init__ et ceux d'autres langues constructeurs est qu' __init__ est pas un constructeur: c'est un initialiseur (le constructeur (le cas échéant, mais, à voir plus tard;-) __new__ et fonctionne complètement différemment de nouveau). Alors que la construction de toutes les super-classes (et, sans doute, de le faire "avant", vous permet de poursuivre la construction vers le bas) est évidemment de la partie pour dire que vous êtes la construction d' une sous-classe de l'instance, qui n'est clairement pas le cas pour l'initialisation, car il existe de nombreux cas d'utilisation dans lequel les super-classes " initialisation doit être ignorée, modifié, contrôlée -- qui se passe, si, "au milieu" de la sous-classe d'initialisation, et ainsi de suite.

Fondamentalement, la super-classe de la délégation de l'initialiseur n'est pas automatique en Python, pour exactement les mêmes raisons, une telle délégation est pas automatique pour toutes les autres méthodes-et notez que ces "autres langues" ne fais pas automatique super-classe de la délégation pour toute autre méthode, soit de... juste pour le constructeur (et, le cas échéant, le destructeur), qui, comme je l'ai mentionné, est pas ce que Python __init__ . (Le comportement de l' __new__ est également tout à fait particulière, mais vraiment pas liés directement à votre question, depuis __new__ est un étrange constructeur qu'il ne fait pas nécessairement besoin de construire quoi que ce soit, pourraient parfaitement bien retourner une instance existante, ou même un non-instance... clairement Python offre vous beaucoup plus de contrôle de la mécanique que les "autres langues" vous avez à l'esprit, qui aussi inclut ayant pas automatique délégation en __new__ lui-même!-).

38voto

Glenn Maynard Points 24451

Je suis un peu gêné quand les gens parrot le "Zen de Python", comme si c'est une justification pour quoi que ce soit. C'est une conception de la philosophie; en particulier, les décisions de conception peut toujours être expliqué en termes plus précis--et ils doivent être, ou encore de la "Zen de Python" devient une excuse pour faire n'importe quoi.

La raison en est simple: vous n'avez pas nécessairement construire une classe dérivée d'une manière similaire à la façon dont on construit la classe de base. Vous pouvez avoir plus de paramètres, de moins en moins, ils peuvent être dans un ordre différent ou pas.

class myFile(object):
    def __init__(self, filename, mode):
        self.f = open(filename, mode)
class readFile(myFile):
    def __init__(self, filename):
        super(readFile, self).__init__(filename, "r")
class tempFile(myFile):
    def __init__(self, mode):
        super(tempFile, self).__init__("/tmp/file", mode)
class wordsFile(myFile):
    def __init__(self, language):
        super(wordsFile, self).__init__("/usr/share/dict/%s" % language, "r")

Cela s'applique à tous les dérivées des méthodes, et pas seulement __init__.

22voto

Ben Points 22160

Java et C++ exiger qu'un constructeur de classe de base est appelé à cause de la disposition de la mémoire.

Si vous avez une classe BaseClass avec un membre de l' field1, et vous créez une nouvelle classe SubClass qui ajoute un membre de l' field2, alors une instance de SubClass contient de l'espace pour field1 et field2. Vous avez besoin d'un constructeur de BaseClass de remplissage en field1, sauf si vous avez besoin de toutes les classes héritant de répéter BaseClasss'initialisation dans leurs propres constructeurs. Et si field1 est privé, alors hériter de classes ne peut pas initialiser field1.

Python n'est pas du Java ou du C++. Toutes les instances de toutes les classes définies par l'utilisateur ont la même "forme". Ils sont fondamentalement juste dictionnaires dans lesquels les attributs peuvent être insérés. Avant tout, l'initialisation a été fait, toutes les instances de toutes les classes définies par l'utilisateur sont presque exactement les mêmes, elles sont simplement des endroits pour stocker les attributs qui ne sont pas de stocker tout encore.

Il est donc parfaitement logique pour un Python sous-classe de ne pas appeler son constructeur de classe de base. Il suffirait d'ajouter les attributs d'elle-même si elle le voulait. Il n'y a pas d'espace réservé pour un certain nombre de champs pour chaque classe dans la hiérarchie, et il n'y a pas de différence entre un attribut ajouté par code à partir d'un BaseClass méthode et un attribut ajouté par code à partir d'un SubClass méthode.

Si, comme il est courant, en SubClass réellement ne voulez avoir tous BaseClasss'invariants mis en place avant, il va faire de son propre personnalisation, alors oui vous pouvez les appeler BaseClass.__init__() (ou utilisez super, mais c'est compliqué et a ses propres problèmes, parfois). Mais vous n'avez pas à. Et vous pouvez le faire avant, ou après, ou avec des arguments différents. L'enfer, si vous vouliez vous pourriez appeler l' BaseClass.__init__ d'une autre méthode entièrement de __init__; peut-être que vous avez une étrange initialisation de chose.

Python réalise cette flexibilité en gardant les choses simples. Vous permet d'initialiser les objets par la rédaction d'un __init__ méthode qui définit les attributs self. C'est tout. Il se comporte exactement comme une méthode, parce que c'est exactement une méthode. Il n'y a pas d'autres étranges et peu intuitive des règles au sujet de choses à faire en premier, ou des choses qui se déclencheront automatiquement si vous n'avez pas à faire d'autres choses. Le seul but qu'il doit servir, c'est être un crochet à exécuter au cours de l'initialisation des objets à l'ensemble initial de valeurs d'attribut, et c'est exactement ce qu'. Si vous voulez faire autre chose, de vous écrire explicitement que dans votre code.

11voto

Mike Axiak Points 6349

« Explicit est mieux qu’implicite. » C’est le même raisonnement qui indique que nous devrions écrire explicitement « soi ».

Je pense qu’en fin de compte, c’est un avantage--pouvez vous réciter toutes les règles Java a au sujet de l’appelant surclasse constructeurs ?

7voto

gnibbler Points 103484

La sous-classe a souvent des paramètres supplémentaires qui ne peuvent pas être passés à la superclasse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X