2009-12-24 20 views
5

In Python 2.x, super accetta i seguenti casiPerché python super non accetta solo l'istanza?

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: 

per quanto vedo, super è una classe, avvolgendo il tipo e (eventualmente) l'istanza di risolvere la superclasse di una classe.

Sono piuttosto perplesso da un paio di cose:

  • perché non c'è inoltre super(instance), con utilizzo tipico esempio super(self).__init__(). Tecnicamente, è possibile ottenere il tipo di oggetto dall'oggetto stesso, quindi la strategia corrente super(ClassType, self).__init__() è ridondante. Presumo problemi di compatibilità con classi vecchio stile o eredità multipla, ma mi piacerebbe sentire il tuo punto.
  • perché, d'altra parte, python 3 accetterà (vedi Understanding Python super() with __init__() methods) super().__init__()? Vedo un po 'di magia in questo, violando l'esplicito è meglio dello Zen implicito. Avrei visto più appropriato self.super().__init__().

risposta

6

super(ClassType, self).__init__() è non ridondante in uno schema di ereditarietà multipla di cooperazione - ClassType non è necessariamente il tipo di self, ma la classe da cui si desidera fare la chiamata cooperativa __init__.

nella gerarchia delle classi C inherits B inherits A, in C.__init__ si desidera chiamare init superclasse dal punto di vista C's, e si chiama B.__init__; quindi in B.__init__ è necessario passare il tipo di classe B a super - poiché si desidera risolvere le superclassi di chiamata di B (o piuttosto, il successivo nel mro dopo B della 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__() 

se ora un'istanza c = C(), si vede che il tipo di classe non è ridondante - super(self).__init__() all'interno B.__init__ non sarebbe davvero funziona! Quello che fai è che tu specifichi manualmente in quale classe si trova il metodo che chiama super (questo è risolto in Super di Python 3 da una variabile nascosta che punta alla classe del metodo).

Due collegamenti con esempi di super e l'ereditarietà multipla:

+0

Immagino tu intenda la classe B (A): e la classe C (B): –

+0

Tuttavia, hai ragione. Non sarebbe mai in grado di chiamare A .__ init __() da B, perché nel metodo B .__ init __() self sarebbe di tipo C, il cui super diretto è B, non A. Quindi B .__ init __() verrebbe richiamato. –

+0

ah hai ragione riguardo l'errore di battitura, grazie! E questo diventa ancora più complicato in molteplici schemi di ereditarietà, penso di poter trovare un link al riguardo. – u0b34a0f6ae

3

Non riesco a fornire una risposta specifica, ma avete letto il PEP intorno alla parola chiave super? Ho fatto una breve ricerca su Google e si avvicinò con PEP 367 e PEP 3135.

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

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

A differenza di qualsiasi altra lingua che conosco, il più delle volte si possono trovare le risposte a Python stranezze nel PEP insieme a chiare dichiarazioni razionali e di posizione.

Aggiornamento:

Avendo letto attraverso 3135, messaggi di posta elettronica relativi nella mailing Python e la lingua di riferimento che tipo di senso perché è il modo in cui lo è per Python 2 vs Python 3.

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

Penso che super sia stato implementato per essere esplicito/ridondante solo per essere al sicuro e mantenere la logica coinvolta nel modo più semplice possibile (senza zucchero o logica profonda per trovare il genitore). Poiché super è una funzione incorporata, deve inferire il ritorno corretto da ciò che viene fornito senza aggiungere ulteriori complicazioni alla struttura degli oggetti Python.

PEP 3135 cambia tutto perché ha presentato e vinto un argomento per un approccio DRY'er al super.

+0

Sono d'accordo, ma io sto cercando di ottenere una risposta alla _while_ domanda, allo stesso tempo aumentare informazioni StackOverflow. –

+0

@Stefano Subito dopo aver realizzato il mio post originale ho iniziato a pensare la stessa cosa. – David

Problemi correlati