Welche Beziehung besteht zwischen Bereich und Namespaces in Python?

12

In vielen Ressourcen habe ich festgestellt, dass "Gültigkeitsbereich" und "Namespaces" synonym verwendet werden, was etwas verwirrend erscheint, da sie unterschiedliche Bedeutungen haben.

  • Der Bereich definiert den Bereich des Codes, in dem ein Name verfügbar ist.
  • Die LEGB-Regel definiert, wie Namen nachgeschlagen werden.
  • Der Namespace ist ein Ort, an dem Sie nach Namen suchen.

Dann las ich:

  • "Namen werden an einen Namespace gebunden, je nachdem, wo sie zugewiesen wurden ..." (was meiner Meinung nach der Umgang mit Bereichen im lexikalischen Bereich ist).
  • "Funktionen fügen Ihren Programmen eine zusätzliche Namespace-Ebene hinzu" [ Ref. ] (Fügen sie keinen zusätzlichen lokalen Bereich hinzu?)
  • "Alle in einer Funktionsdefinition zugewiesenen Namen werden in den lokalen Bereich (den mit dem Funktionsaufruf verknüpften Namespace) gestellt."
  • "Globaler Bereich, dh ein Namespace, in dem Variablen, die auf der obersten Ebene der Moduldatei erstellt (zugewiesen) wurden, live sind."

* Alle Zitate stammen aus dem Erlernen von Python 5th Edition, Kapitel 17

Sind Namespaces in Python so, wie Bereiche implementiert werden? Sind sie dasselbe? Kann mich jemand aufklären?

Nikos
quelle
1
Könnten Sie Referenzen für die Zitate angeben - ich könnte eine finden, aber nicht die andere.
Jonrsharpe
1
Namespaces sind nur eine Art von Bereich. Siehe stackoverflow.com/questions/291978/…
Robert Harvey

Antworten:

16

Ein Namespace ist ein Wörterbuch, das Namen (als Zeichenfolgen) Werten zuordnet. Wenn Sie eine Aufgabe a = 1ausführen, mutieren Sie beispielsweise einen Namespace. Wenn Sie eine Referenz erstellen print(a), durchsucht Python eine Liste von Namespaces, um einen mit dem Namen als Schlüssel zu finden.

Ein Bereich definiert, in welchen Namespaces in welcher Reihenfolge gesucht wird. Der Gültigkeitsbereich einer Referenz beginnt immer im lokalen Namespace und bewegt sich nach außen, bis er den globalen Namespace des Moduls erreicht, bevor er zum builtins(dem Namespace, der auf Pythons vordefinierte Funktionen und Konstanten wie rangeund verweist) übergeht getattr, der das Ende der Zeile darstellt .

Stellen Sie sich vor, Sie haben eine Funktion mit dem Namen inner, die in einer globalen Funktion mit dem Namen verschachtelt outerist und innereinen Verweis auf einen Namen enthält. Python sucht zuerst im innerNamespace. Wenn der Name nicht vorhanden ist, sucht Python im outerNamespace. Wenn dies fehlschlägt, versucht Python den globalNamespace des Moduls und dann den builtinNamespace und löst schließlich ein aus, NameErrorwenn der Name nicht gefunden wird.

Wenn wir sagen, dass xes sich im Namespace einer Funktion befindet, meinen wir, dass es dort lokal innerhalb der Funktion definiert ist. Wenn wir sagen, dass xes sich im Funktionsbereich befindet, bedeutet dies, dass xes sich entweder im Namespace der Funktion oder in einem der äußeren Namespaces befindet, in denen der Namespace der Funktion verschachtelt ist.

Wann immer Sie eine Funktion definieren, erstellen Sie einen neuen Namespace und einen neuen Bereich. Der Namespace ist der neue lokale Hash von Namen. Der Bereich ist die implizite Kette von Namespaces, die am neuen Namespace beginnt und sich dann durch alle äußeren Namespaces (äußere Bereiche) bis zum globalen Namespace (dem globalen Bereich) und weiter zu den integrierten Funktionen bewegt.

Die Begriffe können fast synonym verwendet werden, aber das liegt nicht daran, dass sie dasselbe bedeuten. Das liegt daran, dass sie sich in dem, was sie implizieren, stark überschneiden.

Carl Smith
quelle
3
"Die Begriffe können fast synonym verwendet werden, aber das liegt nicht daran, dass sie dasselbe bedeuten, sondern daran, dass sie sich in dem, was sie implizieren, stark überschneiden."
Nikos
2
Diese Antwort ist richtig, aber im Detail falsch. Klassen in Python führen keinen neuen Namespace ein, weshalb Klassenattribute mit dem Klassennamen und Instanzattribute mit dem Instanznamen qualifiziert werden müssen. Die Ebenen des Namespace in Python von innen nach außen sind Local, Enclosing, Global und Built-in. Eine Klasse kann auf jeder dieser Ebenen definiert werden, aber die Mitglieder einer Klasse müssen immer qualifiziert sein.
Rob Smallshire
Du hast recht. Der Unterricht funktioniert nicht so, wie ich es gesagt habe. Ich dachte, sie schaffen einen lexikalischen Bereich wie eine Funktion, aber sie tun es nicht. Bitte aktualisieren Sie die Antwort, wenn Sie Zeit haben, sonst mache ich es irgendwann. Vielen Dank.
Carl Smith
1
+1 Geniale Antwort, die solche Subtilität so wirtschaftlich zusammenfasst. Ich fand das sehr hilfreich, danke!
Sucher
1
"Ein Namespace ist ein Hash aus Namen, Wertepaaren, ähnlich wie ein Python-Wörterbuch" - Ich bin mir ziemlich sicher, dass Namespaces als Python-Wörterbücher gespeichert sind . Sie können beispielsweise den globalen Namespace bearbeiten, indem Sie globals () aufrufen. Dadurch können Sie das Wörterbuch direkt ändern, um Objekte und Namen zu binden: zum Beispiel globals () [name] = "object". Ansonsten tolle Antwort.
Evan Rosica
4

Es gibt einen ausgezeichneten Artikel über Python - Namespaces hier . So zitieren Sie den relevanten Teil, um Ihre Frage zum Verweis zwischen Bereichen und Namespaces zu beantworten:

Ein Bereich bezieht sich auf einen Bereich eines Programms, von dem aus auf einen Namespace ohne Präfix zugegriffen werden kann.

Stellen Sie sich zum Beispiel ein einfaches Würfelprogramm vor:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll hat einen eigenen Namespace , aber die Namen im Namespace des Moduls sind auch im Gültigkeitsbereich .

Jonrsharpe
quelle
@CarlSmith Beachten Sie, dass die frühe Python-Dokumentation dasselbe sagt: "Ein Bereich ist ein
Jonrsharpe
@CarlSmith hat sich neben dem zusätzlichen nicht-lokalen / umschließenden Bereich viel geändert? Ich denke, wir sagen dasselbe - ein Namespace enthält die Namen und Werte, und der Bereich gibt an, auf welche Namespaces zugegriffen werden kann.
Jonrsharpe
Ich habe meine alten Kommentare gelöscht.
Carl Smith