class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
Dies ist nicht ganz dasselbe wie ähnliche Dinge in anderen Sprachen und verwendet die globale Suche, anstatt den Zugriff auf zu beschränken outer_var
. (Wenn Sie ändern, an welches Objekt der Name Outer
gebunden ist, verwendet dieser Code dieses Objekt bei der nächsten Ausführung.)
Wenn Sie stattdessen möchten, dass alle Inner
Objekte einen Verweis auf ein Outer
weil haben, outer_var
ist dies wirklich ein Instanzattribut:
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
Beachten Sie, dass das Verschachteln von Klassen in Python etwas ungewöhnlich ist und nicht automatisch eine spezielle Beziehung zwischen den Klassen impliziert. Du bist besser dran, nicht zu nisten. (Sie können immer noch ein Klasse - Attribut auf , Outer
um Inner
, wenn Sie möchten.)
Outer
jedes Mal neu nachgeschlagen wirdInner.inner_var
. Wenn Sie den NamenOuter
an ein neues Objekt binden ,Inner.inner_var
wird dieses neue Objekt zurückgegeben.Ich denke, Sie können einfach tun:
Das Problem, auf das Sie gestoßen sind, ist folgendes:
Das Obige bedeutet:
Ein Funktionskörper ist ein Codeblock und eine Methode ist eine Funktion. Namen, die aus dem in einer Klassendefinition vorhandenen Funktionskörper definiert wurden, erstrecken sich nicht auf den Funktionskörper.
Um dies für Ihren Fall zu umschreiben:
Eine Klassendefinition ist ein Codeblock. Namen, die aus der in einer äußeren Klassendefinition vorhandenen inneren Klassendefinition definiert wurden, erstrecken sich nicht auf die innere Klassendefinition.
quelle
[a + i for i in range(10)]
bindet Ab jedoch erfolgreich an die erwartete Liste [42..51].list(a + i for i in range(10))
istlist((a + i for i in range(10)))
das zu sagenlist(a_generator)
. Sie sagen, dass ein Generator mit einem ähnlichen Umfang wie der Funktionsumfang implementiert ist.list(...)
Aufruf noch das Verständnis funktionieren in Python 3. Die Dokumentation für Py3 ist auch etwas anders, was dies widerspiegelt. Es heißt jetzt " Der Umfang der in einem Klassenblock definierten Namen ist auf den Klassenblock beschränkt; er erstreckt sich nicht auf die Codeblöcke von Methoden - dies schließt Verständnisse und Generatorausdrücke ein, da sie unter Verwendung eines Funktionsumfangs implementiert werden. " ).Sie sind möglicherweise besser dran, wenn Sie keine verschachtelten Klassen verwenden. Wenn Sie nisten müssen, versuchen Sie Folgendes:
Oder deklarieren Sie beide Klassen, bevor Sie sie verschachteln:
(Danach können Sie,
del InnerClass
wenn Sie müssen.)quelle
Einfachste Lösung:
Es erfordert, dass Sie explizit sind, aber nicht viel Aufwand.
quelle
In Python werden veränderbare Objekte als Referenz übergeben, sodass Sie eine Referenz der äußeren Klasse an die innere Klasse übergeben können.
quelle
__del__
der Garbage Collector den Referenzzyklus nicht verarbeiten, wenn Sie eine Methode definiert haben , und die Objekte werden ausgeführtgc.garbage
. Der obige Code ist jedoch nicht problematisch. Der Umgang damit ist die Verwendung einer schwachen Referenz . Sie können die Dokumentation über schwache Referenz (2.7) oder schwache Referenz (3.5)Alle Erklärungen finden Sie in der Python-Dokumentation Das Python-Tutorial
Für Ihren ersten Fehler
<type 'exceptions.NameError'>: name 'outer_var' is not defined
. Die Erklärung lautet:zitiert aus dem Python-Tutorial 9.4
Für Ihren zweiten Fehler
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
zitiert aus dem Python-Tutorial 9.3.1
Wenn Sie es versuchen
inner_var = Outerclass.outer_var
, wurde dasQuterclass
noch nicht erstellt, deshalbname 'OuterClass' is not defined
Eine detailliertere, aber langwierige Erklärung für Ihren ersten Fehler:
zitiert aus Learning.Python (5.) .Mark.Lutz
quelle