Использование super () во вложенных классах - PullRequest
23 голосов
/ 01 декабря 2009

Представьте себе это:

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

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

NameError: global name B is not defined.

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

Обновление:

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

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

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

    someattribute = B()

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

Ответы [ 3 ]

18 голосов
/ 01 декабря 2009

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

>>> 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 голосов
/ 01 декабря 2009

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

class A(object):
    class B(object):
        def __init__(self):
            super(self.__class__, self).__init__()
2 голосов
/ 01 декабря 2009

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

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

...