Nichtlokale Python-Anweisung/Schlüsselwort

Lesezeit: 8 Minuten

Benutzeravatar von ooboo
ooboo

Was macht nonlocal tun in Python 3.x?


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.

    – 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 einer schönes Beispiel.

    – Marmelade

    8. Oktober 2016 um 6:03 Uhr


Benutzeravatar von Anon
Anonym

Vergleichen Sie dies, ohne zu verwenden nonlocal:

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.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

Natürlich könnten Sie dies als Generator schreiben, wie:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

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

Benutzeravatar von Danny Milosavljevic
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.

Benutzeravatar von Yossi Truzman
Yossi Truzmann

help(‘nonlocal’) Die nonlocal Aussage


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

Das 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.

Verwandte Hilfethemen: global, NAMESPACES

Quelle: Python-Sprachreferenz

  • 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

Zitat aus der Python 3-Referenz:

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)

1399550cookie-checkNichtlokale Python-Anweisung/Schlüsselwort

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy