2009-12-24 3 views
5

2.x python, super accepte les cas suivantsPourquoi python super n'accepte pas seulement les instances?

class super(object) 
| super(type) -> unbound super object 
| super(type, obj) -> bound super object; requires isinstance(obj, type) 
| super(type, type2) -> bound super object; requires issubclass(type2, type) 
| Typical use to call a cooperative superclass method: 

pour autant que je vois, super est une classe, enveloppant le type et (éventuellement) l'instance pour résoudre la superclasse d'une classe.

Je suis un peu perplexe par deux choses:

  • pourquoi il n'y a pas non plus super(instance), avec une utilisation typique par exemple super(self).__init__(). Techniquement, vous pouvez obtenir le type d'un objet à partir de l'objet lui-même, de sorte que la stratégie actuelle super(ClassType, self).__init__() est en quelque sorte redondante. J'assume des problèmes de compatibilité avec les classes de style ancien, ou héritage multiple, mais j'aimerais entendre votre point de vue.
  • pourquoi, d'autre part, python 3 acceptera (voir Understanding Python super() with __init__() methods) super().__init__()? Je vois un peu de magie en cela, violant l'explicite est mieux que le Zen implicite. J'aurais vu plus approprié self.super().__init__().

Répondre

6

super(ClassType, self).__init__() est pas redondant dans un système d'héritage multiple coopératif - ClassType est pas nécessairement le type de self, mais la classe dont vous voulez faire l'appel coopérative à __init__.

Dans la hiérarchie des classes C inherits B inherits A, dans C.__init__ vous voulez appeler init superclasse de C's point de vue, et que vous appelez B.__init__; alors dans B.__init__ vous devez passer le type de classe B à super - puisque vous voulez résoudre les superclasses appelantes de B (ou plutôt, le suivant dans le mro après B de la classe C).

class A (object): 
    def __init__(self): 
    pass 

class B (A): 
    def __init__(self): 
    super(B, self).__init__() 

class C (B): 
    def __init__(self): 
    super(C, self).__init__() 

si vous instanciable c = C(), vous voyez que le type de classe n'est pas redondant - super(self).__init__() intérieur B.__init__ ne serait pas vraiment! Qu'est-ce que vous faites est que vous spécifiez manuellement dans quelle classe la méthode appelant super est (un ceci est résolu dans super Python 3 par une variable cachée pointant vers la classe de la méthode).

Deux liens avec des exemples de super et l'héritage multiple:

+0

Je suppose que vous vouliez dire classe B (A): et classe C (B): –

+0

Cependant, vous avez raison. Il ne serait jamais capable d'appeler A .__ init __() de B, car dans la méthode B .__ init __() self serait de type C, dont super direct est B, pas A. Donc B .__ init __() serait appelé à nouveau. –

+0

ah vous avez raison sur la faute de frappe, merci! Et cela devient encore plus compliqué dans les systèmes d'héritage multiple, je pense que je peux trouver un lien à ce sujet. – u0b34a0f6ae

3

Je ne peux pas fournir une réponse spécifique, mais avez-vous lu les PEP autour du super mot-clé? Je l'ai fait une recherche rapide sur Google et il est venu avec PEP 367 et PEP 3135.

http://www.python.org/dev/peps/pep-0367/

http://www.python.org/dev/peps/pep-3135/#numbering-note

Contrairement à toute autre langue que je connais, la plupart du temps, vous pouvez trouver les réponses à Python bizarreries dans le PEP avec des énoncés rationnels et de position claire.

Mise à jour:

Après avoir lu à travers 3135, des e-mails liés à l'envoi Python et la référence du langage, il sorte de logique pourquoi il est la façon dont il est pour Python 2 vs Python 3.

http://docs.python.org/library/functions.html?highlight=super#super

Je pense que super a été implémenté pour être explicite/redondant juste pour être du bon côté et garder la logique impliquée aussi simple que possible (pas de sucre ou de logique profonde pour trouver le parent). Puisque super est une fonction intégrée, elle doit déduire le bon retour de ce qui est fourni sans ajouter plus de complication à la façon dont les objets Python sont structurés.

PEP 3135 change tout parce qu'il a présenté et gagné un argument pour une approche DRY'er à super.

+0

Je suis d'accord, mais je suis en train d'obtenir une réponse à la _while_ question en même temps de plus en plus informations de stackoverflow. –

+0

@Stefano Immédiatement après avoir fait mon post original, j'ai commencé à penser la même chose. – David

Questions connexes