Um Debugging-Fragen zu schließen, wo OP benötigt wird nonlocal und es nicht erkennt, verwenden Sie bitte Ist es möglich, eine Variable in Python zu ändern, die sich im äußeren, aber nicht globalen Bereich befindet? stattdessen.
Obwohl Python 2 ist seit dem 1. Januar 2020 offiziell nicht mehr unterstütztwenn Sie aus irgendeinem Grund gezwungen sind, eine Python 2.x-Codebasis zu pflegen und ein Äquivalent zu benötigen nonlocalsiehe Schlüsselwort nonlocal in Python 2.x.
Schauen Sie sich diese Frage an: stackoverflow.com/questions/1414304/local-functions-in-python
– Matt Tischler
5. Dezember 2010 um 13:50 Uhr
Hier ist die offizielle Python-Website-Dokumentation für nichtlokal: docs.python.org/3/reference/… (Diese Dokumentation ist seit Python 3.0 verfügbar, daher war die Behauptung des OP, dass es keine offizielle Dokumentation gibt, einfach falsch.)
– wkschwartz
3. Oktober 2013 um 17:46 Uhr
"There is no documentation for nonlocal". Eigentlich kannst du das help(keyword_in_string) für Dokumentationen in Python 3 und höher
– rassa45
7. August 2015 um 9:21 Uhr
Um fair zu sein, sind die offiziellen Dokumente zu diesem Thema irgendwie schlecht. Das Beispiel der ausgewählten Antwort macht die Dinge sehr klar und macht dies zu einer wertvollen Frage.
x = 0
def outer():
x = 1
def inner():
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 1
# global: 0
Dazu verwenden nonlocalwo inner()‘s x ist jetzt auch outer()‘s x:
x = 0
def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 2
# global: 0
Wenn wir verwenden würden globales würde binden x auf den richtig “globalen” Wert:
x = 0
def outer():
x = 1
def inner():
global x
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 1
# global: 2
Es ist sehr ähnlich – aber beachten Sie, dass das äußere x im Beispiel nicht global ist, sondern stattdessen in der äußeren Funktion definiert ist.
– Anonym
11. August 2009 um 18:04 Uhr
@Dustin – Wenn Sie Klasse A mit einem Attribut x und einer darin definierten Unterklasse B hätten, würden Sie x innerhalb von B als Ax bezeichnen
– Anonym
11. August 2009 um 18:37 Uhr
Der Code wird beim Definieren innerer Funktionen leicht stark eingerückt und verstößt schließlich gegen die 79-Zeichen-PEP8-Empfehlung. Gibt es eine Möglichkeit, dieses Problem zu umgehen? Kann eine innere Funktion irgendwie außerhalb der äußeren Funktion platziert werden? Ich weiß, die Frage klingt dumm, aber ich meine es ernst.
– tommy.carstensen
12. Februar 2015 um 0:03 Uhr
@tommy.carstensen Sie könnten die Funktion als Argument übergeben, das ist das Schöne an Funktionen höherer Ordnung. Auch in der funktionalen Programmierung wird dies Komposition genannt, Python ist keine reine FP-Sprache, aber Sie können sicherlich mit Funktionen spielen (Generatoren, Funktionen höherer Ordnung sind einige Beispiele).
– superuseroi
30. März 2015 um 21:24 Uhr
Was ist, wenn es 3 verschachtelte Funktionen gibt? Gibt es dann eine Möglichkeit, von der innersten Funktion aus auf alle 4 Ebenen zuzugreifen?
– Rastapopoulos
9. Oktober 2020 um 12:11 Uhr
Kurz gesagt, Sie können einer Variablen Werte in einem äußeren (aber nicht globalen) Gültigkeitsbereich zuweisen. Sehen PEP 3104 für all die blutigen Details.
Eine Google-Suche nach “python nonlocal” ergab den Vorschlag, PEP 3104, das die Syntax und Begründung der Anweisung vollständig beschreibt. Kurz gesagt, es funktioniert genauso wie die global -Anweisung, außer dass sie verwendet wird, um auf Variablen zu verweisen, die weder global noch lokal für die Funktion sind.
Hier ist ein kurzes Beispiel dafür, was Sie damit machen können. Der Zählergenerator kann umgeschrieben werden, um dies zu verwenden, sodass er eher wie die Idiome von Sprachen mit Closures aussieht.
Aber Während dies eine perfekt idiomatische Python ist, scheint die erste Version für Anfänger etwas offensichtlicher zu sein. Die richtige Verwendung von Generatoren durch Aufrufen der zurückgegebenen Funktion führt häufig zu Verwirrung. Die erste Version gibt explizit eine Funktion zurück.
Ich war mir sicher, dass das Schlüsselwort ‘global’ genau das tut – es bearbeitet höhere Umgebungen, bis es eine Variable mit diesem Namen erreicht. Eine Variable x könnte auf Modulebene innerhalb einer Klasse deklariert werden, dann separat in einer Funktion innerhalb dieser Klasse und dann in einer inneren Funktion dieser Funktion – woher weiß sie, auf welches x sie sich beziehen soll?
– ooboo
11. August 2009 um 17:54 Uhr
Die Sache mit global ist, dass es nur für globale Variablen funktioniert. es kann keine Variablen in einem einschließenden, nicht globalen Geltungsbereich sehen.
– SingleNegationElimination
11. Oktober 2009 um 3:53 Uhr
Ich habe den make_counter ausprobiert – er gibt jedoch keinen Generator, sondern eine Funktion zurück. Gibt es eine Möglichkeit, einen Generator zurückzugeben, damit ich später darüber iterieren kann?
– Dejell
5. Dezember 2013 um 17:23 Uhr
@Dejel: dieses Beispiel soll das veranschaulichen nonlocal Anweisung in Python; Wenn Sie eine Folge natürlicher Zahlen wollen, ist das Python-Idiom eigentlich itertools.count()
– SingleNegationElimination
5. Dezember 2013 um 17:28 Uhr
Ich möchte die Möglichkeit demonstrieren, einen Generator wie mit yield zurückzugeben – yield gibt tatsächlich einen Generator zurück. Meine Idee ist, yield nicht zu verwenden und stattdessen vielleicht eine nicht lokale oder eine andere Lösung zu verwenden
– Dejell
5. Dezember 2013 um 17:40 Uhr
Danny Milosavljevic
Es nimmt denjenigen, der dem Bezugspunkt im Quellcode “am nächsten” ist. Das nennt sich „Lexical Scoping“ und ist seit >40 Jahren Standard.
Die Klassenmitglieder von Python befinden sich wirklich in einem Wörterbuch namens __dict__ und wird niemals durch lexikalisches Scoping erreicht.
Wenn Sie nicht angeben nonlocal aber tun x = 7, wird eine neue lokale Variable “x” erstellt. Wenn Sie angeben nonlocal, wird es das “nächste” “x” finden und diesem zuweisen. Wenn Sie angeben nonlocal und es kein “x” gibt, erhalten Sie eine Fehlermeldung.
Das Schlüsselwort global kam mir immer seltsam vor, da es alle anderen “x” bis auf das äußerste gerne ignoriert.
Die nonlocal -Anweisung bewirkt, dass die aufgelisteten Bezeichner auf zuvor gebundene Variablen im nächsten umschließenden Gültigkeitsbereich verweisen. Dies ist wichtig, da das Standardverhalten für die Bindung darin besteht, zuerst den lokalen Namespace zu durchsuchen. Die Anweisung ermöglicht es gekapseltem Code, Variablen außerhalb des lokalen Gültigkeitsbereichs neben dem globalen (Modul-) Gültigkeitsbereich erneut zu binden.
Namen aufgeführt in a nonlocal Anweisung, anders als die in a aufgeführten global -Anweisung auf bereits vorhandene Bindungen in einem umschließenden Gültigkeitsbereich verweisen (der Gültigkeitsbereich, in dem eine neue Bindung erstellt werden soll, kann nicht eindeutig bestimmt werden).
Namen aufgeführt in a nonlocal -Anweisung darf nicht mit bereits bestehenden Bindungen im lokalen Geltungsbereich kollidieren.
Siehe auch:
PEP 3104 – Zugriff auf Namen in äußeren Bereichen
Die Spezifikation für die nonlocal Aussage.
Jeden Tag etwas Neues lernen. Ich hatte keine Ahnung, dass du es gebrauchen könntest help() auf Keywords (und jetzt bin ich umgehauen: help() ohne Argumente geht interaktiv).
Die nichtlokale Anweisung bewirkt, dass die aufgelisteten Bezeichner auf zuvor gebundene Variablen im nächsten umschließenden Gültigkeitsbereich ohne globale Variablen verweisen.
Wie in der Referenz gesagt, wird bei mehreren verschachtelten Funktionen nur die Variable in der nächsten umschließenden Funktion geändert:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print('Inner x has been modified')
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Inner x has been modified
Die “nächste” Variable kann mehrere Ebenen entfernt sein:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Outer x has been modified
Aber es kann keine globale Variable sein:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print('Global x has been modified')
# SyntaxError: no binding for nonlocal 'x' found
Jeden Tag etwas Neues lernen. Ich hatte keine Ahnung, dass du es gebrauchen könntest help() auf Keywords (und jetzt bin ich umgehauen: help() ohne Argumente geht interaktiv).
– Erik Youngren
24. Februar 2014 um 9:05 Uhr
a = 0 #1. global variable with respect to every function in program
def f():
a = 0 #2. nonlocal with respect to function g
def g():
nonlocal a
a=a+1
print("The value of 'a' using nonlocal is ", a)
def h():
global a #3. using global variable
a=a+5
print("The value of a using global is ", a)
def i():
a = 0 #4. variable separated from all others
print("The value of 'a' inside a function is ", a)
g()
h()
i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
14405900cookie-checkWas macht nonlocal in Python 3?yes
Schauen Sie sich diese Frage an: stackoverflow.com/questions/1414304/local-functions-in-python
– Matt Tischler
5. Dezember 2010 um 13:50 Uhr
Hier ist die offizielle Python-Website-Dokumentation für nichtlokal: docs.python.org/3/reference/… (Diese Dokumentation ist seit Python 3.0 verfügbar, daher war die Behauptung des OP, dass es keine offizielle Dokumentation gibt, einfach falsch.)
– wkschwartz
3. Oktober 2013 um 17:46 Uhr
"There is no documentation for nonlocal".
Eigentlich kannst du dashelp(keyword_in_string)
für Dokumentationen in Python 3 und höher– rassa45
7. August 2015 um 9:21 Uhr
Um fair zu sein, sind die offiziellen Dokumente zu diesem Thema irgendwie schlecht. Das Beispiel der ausgewählten Antwort macht die Dinge sehr klar und macht dies zu einer wertvollen Frage.
– Verrückter Physiker
27. Mai 2016 um 20:14 Uhr
Im offiziellen Python-Tutorial gibt es eine gute Erklärung des Konzepts von Gültigkeitsbereichen und Namespaces mit einem schönes Beispiel.
– Marmelade
8. Oktober 2016 um 6:03 Uhr