class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
Это не совсем то же самое, что аналогичные вещи работают на других языках, и использует глобальный поиск вместо определения области доступа к outer_var
. (Если вы измените объект, к Outer
которому привязано имя , этот код будет использовать этот объект при следующем выполнении.)
Если вместо этого вы хотите, чтобы все Inner
объекты имели ссылку на, Outer
потому что outer_var
это действительно атрибут экземпляра:
class Outer(object):
def __init__(self):
self.outer_var = 1
def get_inner(self):
return self.Inner(self)
# "self.Inner" is because Inner is a class attribute of this class
# "Outer.Inner" would also work, or move Inner to global scope
# and then just use "Inner"
class Inner(object):
def __init__(self, outer):
self.outer = outer
@property
def inner_var(self):
return self.outer.outer_var
Обратите внимание, что вложенные классы несколько необычны в Python и автоматически не подразумевают каких-либо особых отношений между классами. Лучше не влезать. (Вы все еще можете установить атрибут класса на , Outer
чтобы Inner
, если вы хотите.)
Outer
каждый раз просматривается зановоInner.inner_var
. Поэтому, если вы повторно привяжете имяOuter
к новому объекту,Inner.inner_var
начнется возврат этого нового объекта.Я думаю, вы можете просто сделать:
Проблема, с которой вы столкнулись, связана с этим:
Вышеупомянутое означает:
тело функции - это блок кода, а метод - это функция, тогда имена, определенные вне тела функции, присутствующей в определении класса, не распространяются на тело функции.
Перефразируя это для вашего случая:
определение класса - это блок кода, тогда имена, определенные из определения внутреннего класса, присутствующего в определении внешнего класса, не распространяются на определение внутреннего класса.
источник
[a + i for i in range(10)]
успешно связывает Ab с ожидаемым списком [42..51].list(a + i for i in range(10))
этоlist((a + i for i in range(10)))
то естьlist(a_generator)
. Они говорят, что генератор реализован с той же областью действия, что и объем функций.list(...)
вызов, ни понимание не работают в Python 3. Документация для Py3 также немного отличается, отражая это. Он теперь говорит , что « Объем имен , определенные в классе блоке ограничивается блоком класса, он не распространяется на блоки кода методов - это включает в себя постижения . И выражение генератора , так как они реализованы с использованием функцией сферы » (курсив моего ).Возможно, вам будет лучше, если вы просто не будете использовать вложенные классы. Если вам нужно гнездо, попробуйте следующее:
Или объявите оба класса перед их вложением:
(После этого вы можете,
del InnerClass
если вам нужно.)источник
Самое простое решение:
Это требует от вас откровенности, но не требует больших усилий.
источник
В Python изменяемые объекты передаются как ссылки, поэтому вы можете передать ссылку на внешний класс внутреннему классу.
источник
__del__
метод, сборщик мусора не сможет обрабатывать ссылочный цикл, и объекты войдут в негоgc.garbage
. Приведенный выше код, как есть, не вызывает проблем. Чтобы справиться с этим, используйте слабую ссылку . Вы можете прочитать документацию по weakref (2.7) или weakref (3.5)Все объяснения можно найти в документации Python The Python Tutorial
За вашу первую ошибку
<type 'exceptions.NameError'>: name 'outer_var' is not defined
. Объяснение таково:цитируется из The Python Tutorial 9.4
За вашу вторую ошибку
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
цитируется из The Python Tutorial 9.3.1
Итак, когда вы пытаетесь
inner_var = Outerclass.outer_var
, онQuterclass
еще не создан, поэтомуname 'OuterClass' is not defined
Более подробное, но утомительное объяснение вашей первой ошибки:
цитата из Learning.Python (5th) .Mark.Lutz
источник