Come si inizializza la (super) classe di base?


126

In Python, considera che ho il seguente codice:

>>> class SuperClass(object):
    def __init__(self, x):
        self.x = x

>>> class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

Come si inizializza il SuperClass __init__nella sottoclasse? Sto seguendo il tutorial di Python e non lo copre. Quando ho cercato su Google, ho trovato più di un modo di fare. Qual è il modo standard di gestirlo?

Risposte:


147

Python (fino alla versione 3) supporta classi "vecchio stile" e nuovo stile. Le classi di nuovo stile derivano da objectciò che stai utilizzando e invocano la loro classe di base super(), ad es

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Poiché python conosce le classi vecchio e nuovo stile, ci sono diversi modi per invocare un metodo di base, motivo per cui hai trovato diversi modi per farlo.

Per completezza, le classi vecchio stile chiamano i metodi di base esplicitamente usando la classe base, ie

def doit(self, foo):
  return X.doit(self, foo)

Ma dal momento che non dovresti più usare il vecchio stile, non mi importerebbe più di tanto.

Python 3 conosce solo le classi in nuovo stile (non importa se derivi objecto meno).


38

Tutti e due

SuperClass.__init__(self, x)

o

super(SubClass,self).__init__( x )

funzionerà (io preferisco il 2 ° perché aderisce maggiormente al principio DRY).

Vedi qui: http://docs.python.org/reference/datamodel.html#basic-customization


8
sbagliato. super funziona solo con classi nuovo stile ed è l'unico modo corretto per chiamare una base quando si usano classi nuovo stile. Inoltre, è anche necessario passare esplicitamente "self" utilizzando il costrutto vecchio stile.
Ivo van der Wijk

1
@Ivo - l'OP ha fornito una classe di nuovo stile nell'esempio, e non ha molto senso parlare della differenza tra nuovo e vecchio stile poiché nessuno dovrebbe più usare il vecchio stile. Il collegamento che ho fornito (alla documentazione di Python) suggerisce che esiste più di un modo "corretto" per chiamare la superclasse __init__.
adamk


21

Come si inizializza la (super) classe di base?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

Usa un superoggetto per assicurarti di ottenere il metodo successivo (come metodo associato) nell'ordine di risoluzione del metodo. In Python 2, devi passare il nome della classe e selfa super per cercare il __init__metodo associato :

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

In Python 3, c'è un po 'di magia che rende gli argomenti superinutili e, come vantaggio collaterale, funziona un po' più velocemente:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

L'hardcoding del genitore come questo di seguito ti impedisce di utilizzare l'ereditarietà multipla cooperativa:

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

Nota che __init__può solo restituireNone : è destinato a modificare l'oggetto sul posto.

Qualcosa __new__

C'è un altro modo per inizializzare le istanze, ed è l'unico modo per le sottoclassi di tipi immutabili in Python. Quindi è necessario se si vuole sottoclasse stro tupleo di un altro oggetto immutabile.

Potresti pensare che sia un metodo di classe perché ottiene un argomento di classe implicito. Ma in realtà è un metodo statico . Quindi è necessario chiamare __new__con clsesplicito.

Di solito restituiamo l'istanza da __new__, quindi se lo fai, devi anche chiamare anche __new__via superla tua base nella tua classe base. Quindi, se usi entrambi i metodi:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3 elude un po 'la stranezza delle super chiamate causate __new__dall'essere un metodo statico, ma è comunque necessario passare clsal __new__metodo non vincolato :

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.