2009-12-01 5 views
19

Представьте себе:Использование супер() во вложенных классах

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

Это создает ошибку:

 
NameError: global name B is not defined. 

Я попытался A.B, но он говорит, что A не определен.

Update:

Я нашел проблему.

У меня был класс, как это:

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

    someattribute = B() 

В этой области видимости еще не определена.

+0

Использование Python 2.6 и 'AB', а также' самостоятельно .__ class__', кажется, работать. –

+0

'A.B' отлично работает для меня. Но вы уверены, что вам нужно многократное наследование и «супер» здесь? Не прыгайте в мир MI, если вам это действительно не нужно (обычно нет). Если вы это сделаете, вам нужно разрешить и передать сквозные '* args' и' ** kwargs' в ваш '__init__'. – bobince

+0

A не определен в своем собственном блоке класса, поэтому переменная класса '_inner = B()' не будет работать. – u0b34a0f6ae

ответ

16

Я не уверен, почему AB правильно не работает для вас, как и положено .. Вот некоторые выходной оболочки, которая работает:

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

Поскольку B не будет, вероятно, никогда не будет продлен на себя, это должно работать:

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

Если класс AB вряд ли участвовать в какой-либо множественного наследования, то вам лучше всего жесткого кодирования вызов конструктора:

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

Но если вы действительно должны иметь полную силу супер, то вы можете получить то, что вы хотите, определив пользовательский дескриптор, который будет инициализировать атрибут B лениво:

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) 

Это приведет атрибут B к быть создан в первый раз, это доступ, а затем повторно после:

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

Для получения дополнительной информации о дескрипторы, см: http://users.rcn.com/python/download/Descriptor.htm