Articles

Was sind Python-Namespaces (und warum werden sie benötigt?)

Namenskonflikte passieren die ganze Zeit im wirklichen Leben. Zum Beispiel hatte jede Schule, die ich jemals besucht habe, mindestens zwei Schüler in meiner Klasse, die denselben Vornamen hatten. Wenn jemand in die Klasse käme und nach Schüler X fragen würde, würden wir begeistert fragen: „Von welchem redest du? Es gibt zwei Studenten mit dem Namen X.“ Danach würde uns die anfragende Person einen Nachnamen geben, und wir würden ihn dem richtigen X vorstellen.

All diese Verwirrung und der Prozess der Bestimmung der genauen Person, über die wir sprechen, indem wir nach anderen Informationen als einem Vornamen suchen, könnten vermieden werden, wenn jeder einen eindeutigen Namen hätte. In einer Klasse von 30 Schülern ist das kein Problem. Es wird jedoch immer schwieriger, für jedes Kind in einer Schule, Stadt, Stadt, Land oder auf der ganzen Welt einen eindeutigen, aussagekräftigen und leicht zu merkenden Namen zu finden. Ein weiteres Problem bei der Bereitstellung eines eindeutigen Namens für jedes Kind besteht darin, dass der Prozess der Bestimmung, ob jemand anderes sein Kind auch Macey, Maci oder Macie genannt hat, sehr anstrengend sein kann.

Ein sehr ähnlicher Konflikt kann auch in der Programmierung auftreten. Wenn Sie ein Programm mit nur 30 Zeilen ohne externe Abhängigkeiten schreiben, ist es sehr einfach, allen Variablen eindeutige und aussagekräftige Namen zu geben. Das Problem tritt auf, wenn ein Programm Tausende von Zeilen enthält und Sie auch einige externe Module geladen haben. In diesem Tutorial erfahren Sie mehr über Namespaces, ihre Bedeutung und Bereichsauflösung in Python.

Was sind Namespaces?

Ein Namespace ist im Grunde ein System, um sicherzustellen, dass alle Namen in einem Programm eindeutig sind und ohne Konflikte verwendet werden können. Vielleicht wissen Sie bereits, dass alles in Python—wie Strings, Listen, Funktionen usw.-ist ein Objekt. Eine weitere interessante Tatsache ist, dass Python Namespaces als Wörterbücher implementiert. Es gibt eine Zuordnung von Name zu Objekt, wobei die Namen als Schlüssel und die Objekte als Werte dienen. Mehrere Namespaces können denselben Namen verwenden und einem anderen Objekt zuordnen. Hier sind einige Beispiele für Namespaces:

  • Lokaler Namespace: Dieser Namespace enthält lokale Namen innerhalb einer Funktion. Dieser Namespace wird beim Aufruf einer Funktion erstellt und dauert nur so lange, bis die Funktion zurückkehrt.
  • Globaler Namespace: Dieser Namespace enthält Namen aus verschiedenen importierten Modulen, die Sie in einem Projekt verwenden. Es wird erstellt, wenn das Modul in das Projekt aufgenommen wird, und dauert bis zum Ende des Skripts.
  • Integrierter Namespace: Dieser Namespace enthält integrierte Funktionen und integrierte Ausnahmenamen.

In der Reihe Mathematical Modules in Python auf Envato Tuts+ habe ich über nützliche mathematische Funktionen geschrieben, die in verschiedenen Modulen verfügbar sind. Zum Beispiel haben die math- und cmath-Module viele Funktionen, die beiden gemeinsam sind, wie log10()acos()cos()exp() usw. Wenn Sie beide Module im selben Programm verwenden, können Sie diese Funktionen nur eindeutig verwenden, indem Sie ihnen den Namen des Moduls voranstellen, z. B. math.log10() und cmath.log10().

Was ist Scope?

Namespaces helfen uns, alle Namen innerhalb eines Programms eindeutig zu identifizieren. Dies bedeutet jedoch nicht, dass wir einen Variablennamen überall verwenden können, wo wir möchten. Ein Name hat auch einen Bereich, der die Teile des Programms definiert, in denen Sie diesen Namen ohne Präfix verwenden können. Genau wie Namespaces gibt es auch mehrere Bereiche in einem Programm. Hier finden Sie eine Liste einiger Bereiche, die während der Ausführung eines Programms vorhanden sein können.

  • Ein lokaler Bereich, der der innerste Bereich ist, der eine Liste lokaler Namen enthält, die in der aktuellen Funktion verfügbar sind.
  • Ein Bereich aller umschließenden Funktionen. Die Suche nach einem Namen beginnt am nächsten umschließenden Bereich und bewegt sich nach außen.
  • Ein Bereich auf Modulebene, der alle globalen Namen des aktuellen Moduls enthält.
  • Der äußerste Bereich, der eine Liste aller integrierten Namen enthält. Dieser Bereich wird zuletzt durchsucht, um den Namen zu finden, auf den Sie verwiesen haben.

In den kommenden Abschnitten dieses Tutorials werden wir die integrierte Python-Funktion dir() ausführlich verwenden, um eine Liste von Namen im aktuellen lokalen Bereich zurückzugeben. Dies wird Ihnen helfen, das Konzept von Namespaces und Scope klarer zu verstehen.

Bereichsauflösung

Wie ich im vorherigen Abschnitt erwähnt habe, beginnt die Suche nach einem bestimmten Namen bei der innersten Funktion und bewegt sich dann immer höher, bis das Programm diesen Namen einem Objekt zuordnen kann. Wenn in keinem der Namespaces ein solcher Name gefunden wird, löst das Programm eine NameError-Ausnahme aus.

Bevor wir beginnen, versuchen Sie, dir() in IDLE oder einer anderen Python-IDE einzugeben.

dir()# 

Sehen wir uns die Ausgabe der dir() -Funktion an, nachdem wir eine Variable und eine Funktion definiert haben.

a_num = 10dir()# def some_func(): b_num = 11 print(dir()) some_func()# dir()# 

Die dir() Funktion gibt nur die Liste der Namen innerhalb des aktuellen Bereichs aus. Aus diesem Grund gibt es innerhalb des Bereichs von some_func() nur einen Namen namens b_num . Der Aufruf von dir() nach der Definition von some_func() fügt es der Liste der im globalen Namespace verfügbaren Namen hinzu.

Sehen wir uns nun die Liste der Namen in einigen verschachtelten Funktionen an. Der Code in diesem Block wird vom vorherigen Block fortgesetzt.

Der obige Code definiert zwei Variablen und eine Funktion innerhalb des Bereichs von outer_func() . Innerhalb von inner_func() gibt die Funktion dir() nur den Namen d_num aus. Dies scheint fair zu sein, da d_num die einzige dort definierte Variable ist.

Sofern nicht explizit mit global angegeben, wird durch die Neuzuweisung eines globalen Namens in einem lokalen Namespace eine neue lokale Variable mit demselben Namen erstellt. Dies geht aus dem folgenden Code hervor.

Innerhalb von outer_func() und inner_func() wurde a_num als globale Variable deklariert. Wir setzen nur einen anderen Wert für dieselbe globale Variable. Aus diesem Grund ist der Wert von a_num an allen Stellen 20. Andererseits erstellt jede Funktion ihre eigene b_num Variable mit einem lokalen Gültigkeitsbereich, und die print() Funktion gibt den Wert dieser Variablen mit lokalem Gültigkeitsbereich aus.

Module richtig importieren

Es ist sehr üblich, externe Module in Ihre Projekte zu importieren, um die Entwicklung zu beschleunigen. Es gibt drei verschiedene Möglichkeiten, Module zu importieren. In diesem Abschnitt erfahren Sie mehr über all diese Methoden und besprechen deren Vor- und Nachteile im Detail.

  • from module import *: Diese Methode zum Importieren eines Moduls importiert alle Namen des angegebenen Moduls direkt in Ihren aktuellen Namespace. Sie könnten versucht sein, diese Methode zu verwenden, da Sie damit eine Funktion direkt verwenden können, ohne den Namen des Moduls als Präfix hinzuzufügen. Es ist jedoch sehr fehleranfällig, und Sie verlieren auch die Möglichkeit zu erkennen, welches Modul diese Funktion tatsächlich importiert hat. Hier ist ein Beispiel für die Verwendung dieser Methode:

Wenn Sie mit den Modulen math und cmath vertraut sind, wissen Sie bereits, dass es einige gebräuchliche Namen gibt, die in diesen beiden Modulen definiert sind, aber für reelle bzw. komplexe Zahlen gelten.

Da wir das cmath-Modul nach dem Math-Modul importiert haben, überschreibt es die Funktionsdefinitionen dieser allgemeinen Funktionen aus dem Math-Modul. Aus diesem Grund gibt das erste log10(125) eine reelle Zahl und das zweite log10(125) eine komplexe Zahl zurück. Es gibt keine Möglichkeit für Sie, die log10() Funktion aus dem Math-Modul jetzt zu verwenden. Selbst wenn Sie versucht haben, math.log10(125) einzugeben, erhalten Sie eine NameError-Ausnahme, da math im Namespace nicht vorhanden ist.

Die Quintessenz ist, dass Sie diese Art des Importierens von Funktionen aus verschiedenen Modulen nicht verwenden sollten, nur um ein paar Tastenanschläge zu speichern.

  • from module import nameA, nameB: Wenn Sie wissen, dass Sie nur einen oder zwei Namen aus einem Modul verwenden, können Sie diese direkt mit dieser Methode importieren. Auf diese Weise können Sie den Code präziser schreiben und gleichzeitig die Namespace-Verschmutzung auf ein Minimum beschränken. Beachten Sie jedoch, dass Sie mit module.nameZ immer noch keinen anderen Namen aus dem Modul verwenden können. Jede Funktion, die denselben Namen in Ihrem Programm hat, überschreibt auch die Definition dieser Funktion, die aus dem Modul importiert wurde. Dadurch wird die importierte Funktion unbrauchbar. Hier ist ein Beispiel für die Verwendung dieser Methode:
dir()# from math import log2, log10dir()# log10(125)# 2.0969100130080562
  • import module: Dies ist die sicherste und empfohlene Methode zum Importieren eines Moduls. Der einzige Nachteil ist, dass Sie allen Namen, die Sie im Programm verwenden werden, den Namen des Moduls voranstellen müssen. Sie können jedoch Namespace-Verschmutzung vermeiden und auch Funktionen definieren, deren Namen mit dem Namen von Funktionen aus dem Modul übereinstimmen.
dir()# import mathdir()# math.log10(125)# 2.0969100130080562

Abschließende Gedanken

Ich hoffe, dieses Tutorial hat Ihnen geholfen, Namespaces und ihre Bedeutung zu verstehen. Sie sollten nun in der Lage sein, den Umfang verschiedener Namen in einem Programm zu bestimmen und mögliche Fallstricke zu vermeiden. Zögern Sie nicht, zu sehen, was wir auf dem Markt zum Verkauf und zum Studium anbieten, und zögern Sie nicht, Fragen zu stellen und Ihr wertvolles Feedback über den Feed unten zu geben.

Im letzten Abschnitt des Artikels wurden verschiedene Möglichkeiten zum Importieren von Modulen in Python und die Vor- und Nachteile der einzelnen Module erörtert. Wenn Sie Fragen zu diesem Thema haben, lassen Sie es mich bitte in den Kommentaren wissen.

Python lernen

Lernen Sie Python mit unserem vollständigen Python-Tutorial, egal ob Sie gerade erst anfangen oder ein erfahrener Programmierer sind, der neue Fähigkeiten erlernen möchte.