class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
To nie jest to samo, co podobne rzeczy działają w innych językach i używa wyszukiwania globalnego zamiast ograniczania dostępu do outer_var
. (Jeśli zmienisz obiekt, do którego Outer
jest przypisana nazwa , kod użyje tego obiektu przy następnym wykonaniu).
Jeśli zamiast tego chcesz, aby wszystkie Inner
obiekty miały odniesienie do atrybutu, Outer
ponieważ outer_var
jest to naprawdę atrybut instancji:
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
Zauważ, że zagnieżdżanie klas jest dość rzadkie w Pythonie i nie oznacza automatycznie żadnego specjalnego związku między klasami. Lepiej nie zagnieżdżać się. (Nadal można ustawić atrybut class na Outer
celu Inner
, jeśli chcesz).
Outer
jest wyszukiwane na nowo za każdym razem, gdy to robiszInner.inner_var
. Więc jeśli ponownie powiążesz nazwęOuter
z nowym obiektem,Inner.inner_var
zacznie zwracać ten nowy obiekt.Myślę, że możesz po prostu zrobić:
Przyczyną napotkanego problemu jest:
Powyższe oznacza, że:
ciało funkcji jest blokiem kodu, a metoda jest funkcją, wtedy nazwy zdefiniowane poza treścią funkcji w definicji klasy nie rozciągają się na treść funkcji.
Parafrazując to dla twojego przypadku:
definicja klasy jest blokiem kodu, wtedy nazwy zdefiniowane poza definicją klasy wewnętrznej obecnej w definicji klasy zewnętrznej nie rozciągają się na definicję klasy wewnętrznej.
źródło
[a + i for i in range(10)]
powodzeniem wiąże Ab z oczekiwaną listą [42..51].list(a + i for i in range(10))
tolist((a + i for i in range(10)))
znaczylist(a_generator)
. Mówią, że generator jest zaimplementowany w podobnym zakresie niż zakres funkcji.list(...)
wywołanie, ani rozumienie nie działają w Pythonie 3. Dokumentacja dla Py3 jest również nieco inna, co odzwierciedla to. Teraz mówi: „ Zakres nazw zdefiniowanych w bloku klasy jest ograniczony do bloku klasy, ale nie obejmuje bloki kodu metod - obejmuje to listowych . I wyrażeń generatora, ponieważ są one zaimplementowane przy użyciu zakresu funkcji ” (Kopalnia nacisk ).Lepiej by było, gdybyś po prostu nie używał klas zagnieżdżonych. Jeśli musisz zagnieżdżać, spróbuj tego:
Lub zadeklaruj obie klasy przed ich zagnieżdżeniem:
(Po tym możesz,
del InnerClass
jeśli zajdzie taka potrzeba).źródło
Najłatwiejsze rozwiązanie:
Wymaga od ciebie wyraźnego, ale nie wymaga dużego wysiłku.
źródło
W Pythonie zmienne obiekty są przekazywane jako referencje, więc możesz przekazać odwołanie do klasy zewnętrznej do klasy wewnętrznej.
źródło
__del__
metodę, garbage collector nie będzie w stanie obsłużyć cyklu referencyjnego, a obiekty wejdą dogc.garbage
. Powyższy kod, taki jak jest, nie jest jednak problematyczny. Aby sobie z tym poradzić, użyj słabego odniesienia . Możesz przeczytać dokumentację o słabymref (2.7) lub słabymref (3.5)Wszystkie wyjaśnienia można znaleźć w dokumentacji Pythona The Python Tutorial
Twój pierwszy błąd
<type 'exceptions.NameError'>: name 'outer_var' is not defined
. Wyjaśnienie jest następujące:cytowane z The Python Tutorial 9.4
Drugi błąd
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
cytat z The Python Tutorial 9.3.1
Więc kiedy próbujesz
inner_var = Outerclass.outer_var
,Quterclass
plik nie został jeszcze utworzony, dlategoname 'OuterClass' is not defined
Bardziej szczegółowe, ale żmudne wyjaśnienie pierwszego błędu:
cytowane z Learning.Python (5th) .Mark.Lutz
źródło