2009-12-01 29 views
19

Immaginate questo:Usando super() in classi nidificate

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

Questo crea un errore:

 
NameError: global name B is not defined. 

Ho provato A.B, ma poi si dice che A non è definito.

Aggiornamento:

ho trovato il problema.

Ho avuto una classe come questa:

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

    someattribute = B() 

In tale ambito, A non è ancora definita.

+0

Usare Python 2.6 sia AB', così come '' self .__ class__', sembrano lavorare. –

+0

'A.B' funziona bene per me. Ma sei sicuro di aver bisogno dell'eredità multipla e di 'super' qui? Non saltare nel mondo MI a meno che non ne abbia davvero bisogno (di solito non lo fai). Se si va in questo modo è necessario consentire e passare '* args' e' ** kwargs' nel proprio '__init__'. – bobince

+0

A non è definito nel proprio blocco di classe, quindi una variabile di classe A '_inner = B()' non funzionerà. – u0b34a0f6ae

risposta

16

io non sono sicuro perché AB non funziona correttamente per voi, come dovrebbe .. Ecco un output shell che funziona:

>>> class A(object): 
... class B(object): 
...  def __init__(self): 
...  super(A.B, self).__init__() 
... def getB(self): 
...  return A.B() 
... 
>>> A().getB() 
<__main__.B object at 0x100496410> 
5

Dal B sarà probabilmente mai si estese, questo dovrebbe funzionare:

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

Se la classe AB è improbabile che partecipare a qualsiasi ereditarietà multipla, allora sei meglio solo hard-codifica la chiamata al costruttore:

class A(object): 
    class B(object): 
     def __init__(self): 
      object.__init__(self) 

Ma se si ha realmente bisogno di avere tutta la potenza di super, allora si può ottenere ciò che si vuole attraverso la definizione di un descrittore personalizzato che inizializza l'attributo B pigramente:

class LazyAttribute(object): 
    def __init__(self, func, *args, **kwargs): 
     self._func = func 
     self._args = args 
     self._kwargs = kwargs 
     self._value = None 

    def __get__(self, obj, type=None): 
     if self._value is None: 
      print 'created', self._value 
      self._value = self._func(*self._args, **self._kwargs) 
     return self._value 

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

    someattribute = LazyAttribute(B) 

Questo farà sì che l'attributo B a un'istanza la prima volta che viene letta, e quindi riutilizzato in seguito:

>>> print A.someattribute 
created <__main__.B object at 0x00AA8E70> 
<__main__.B object at 0x00AA8E90> 
>>> print A().someattribute 
<__main__.B object at 0x00AA8E90> 

Per maggiori informazioni su descrittori, si veda: http://users.rcn.com/python/download/Descriptor.htm

Problemi correlati