Я хотел бы добиться чего-то похожего на эту конструкцию:
class Outer:
class A:
foo = 1
class B:
def __init__(self):
self.bar = A.foo
Outer.B().bar # ==> 1
Но это не срабатывает
NameError: name 'A' is not defined
Я даже не уверен, что понимаю, почему, как я думал, A
входит в сферу охвата.
Не могли бы вы помочь мне прояснить, почему это не работает и как я могу это обойти?
@ juanpa.arrivillaga Хорошо, я не осознавал, что области действия классов различаются. Я согласен с тем, что это не очень распространенный шаблон, и я использую его здесь только впервые, в основном у меня есть два очень маленьких вспомогательных класса (в основном " контейнеры »для атрибутов класса), и я не думаю, что стоит переносить это в модуль. Кроме того, эти два небольших класса не предназначены для использования в общедоступном интерфейсе.
Имена ищутся Только в globals
, locals
и нелокальных ячейках (но здесь нет закрытия).
Напишите Outer.A
вместо A
или подумайте о том, чтобы сделать Outer
модулем.
Действительно, очень просто, я изначально думал, что Outer не будет доступен, так как класс еще не создан.
Outer
недоступен для кода, выполняемого в области класса. Он является доступен для кода, выполняемого в области действия функции, поскольку функции выполняются только позже. Также обратите внимание, что __class__
существует, но в основном он полезен для reload
или скопированного кода для предотвращения опечаток.
Работает, если вы используете Outer.A.foo
.
Точно так же, как вы сделали для Outer.B().bar
: сделайте то же самое для self.bar=Outer.A().foo
Внутренние классы в Python не имеют доступа к членам включающего класса. Как вы утверждаете, A не входит в сферу действия B. A и B оба входят в область действия Outer, но они не знают друг друга. Поэтому возможное решение вашей проблемы:
class Outer:
class A:
foo = 1
class B:
def __init__(self, class_a):
self.bar = class_a.foo
def __init__(self):
self.a = self.A()
self.b = self.B(self.a)
print(Outer.A.foo) # 1
print(Outer.B.bar) # AttributeError: type object 'B' has no attribute 'bar'
outer = Outer()
print(outer.a.foo) # 1
print(outer.b.bar) # 1
Нет, области действия класса не создают ограничивающие области действия. Вот почему в методе, который вы можете использовать
A
, вам придется использоватьOuter.A
, как и вB.__init__
. Но почему вы для начала используете вложенные классы? Это не общий шаблон в Python ... что это за преимущество?