2009-12-01 11 views
19

Imagine esto:El uso de super() en las clases anidadas

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

Esto crea un error:

 
NameError: global name B is not defined. 

He intentado A.B, pero luego se dice que A no está definido.

Actualización:

que he encontrado el problema.

que he tenido una clase como esta:

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

    someattribute = B() 

En ese ámbito, A no está definido todavía.

+0

el uso de Python 2.6, tanto 'AB', así como' self .__ class__', parecen trabajar. –

+0

'A.B' funciona bien para mí. ¿Pero está seguro de que necesita herencia múltiple y 'super' aquí? No salte al mundo MI a menos que realmente lo necesite (generalmente no lo necesita). Si vas por ese camino, debes permitir y transferir '* args' y' ** kwargs' en tu '__init__'. – bobince

+0

A no está definido en su propio bloque de clases, por lo que una variable de clase A ''inner = B()' no funcionará. – u0b34a0f6ae

Respuesta

16

No estoy seguro de por qué AB no está funcionando correctamente para que, como debe ser .. Aquí hay algo que funciona salida de la shell:

>>> 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

Puesto que B es probable que nunca se puede extender en sí, esto debería funcionar:

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

Si la clase AB es poco probable que participar en ninguna herencia múltiple, entonces es mejor simplemente difíciles de codificar la llamada al constructor:

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

Pero si realmente es necesario tener todo el poder de súper, entonces se puede obtener lo que quiere mediante la definición de un descriptor personalizado que inicializar el atributo B con pereza:

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) 

Esto hará que el atributo B una instancia de la primera vez que se accede, y luego volver a utilizar a partir de entonces:

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

Para obtener más información sobre los descriptores, ver: http://users.rcn.com/python/download/Descriptor.htm