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

Namenskonflikte finden im realen Leben immer wieder statt. Zum Beispiel hatte jede Schule, an der ich je war, mindestens zwei Schüler in meiner Klasse, die denselben Vornamen hatten. Wenn jemand in die Klasse kam und nach Schüler X fragte, fragten wir begeistert: "Von welcher sprechen Sie? Es gibt zwei Schüler mit dem Namen X." Danach gab uns die anfragende Person einen Nachnamen, und wir stellten ihn dem richtigen X vor.

All diese Verwirrung und der Prozess der Ermittlung der genauen Person, von der wir sprechen, indem neben einem Vornamen nach anderen Informationen gesucht wird, könnte vermieden werden, wenn jeder einen eindeutigen Namen hätte. Dies ist in einer Klasse von 30 Schülern kein Problem. Es wird jedoch zunehmend schwieriger, mit a einzigartig, sinnvoll und leicht zu erinnern Name für jedes Kind in einer Schule, Stadt, Stadt, Land oder der ganzen Welt. Ein weiteres Problem bei der Vergabe eines eindeutigen Namens für jedes Kind ist, dass die Feststellung, ob ein anderes Kind auch Macey, Maci oder Macie genannt hat, sehr anstrengend sein kann.

Ein sehr ähnlicher Konflikt kann auch bei 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 entsteht, wenn in einem Programm Tausende von Zeilen vorhanden sind und Sie auch einige externe Module geladen haben. In diesem Lernprogramm erfahren Sie mehr über Namespaces, deren Bedeutung und die Auflösung des Bereichs in Python. 

Was sind Namespaces??

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

  • Lokaler Namespace: Dieser Namespace enthält lokale Namen in einer Funktion. Dieser Namespace wird beim Aufrufen einer Funktion erstellt und dauert nur bis die Funktion zurückkehrt.
  • Global 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 das Skript beendet ist.
  • Eingebauter Namespace: Dieser Namespace enthält integrierte Funktionen und integrierte Ausnahmenamen.

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

Was ist Umfang??

Namensräume helfen uns, alle Namen in einem Programm eindeutig zu identifizieren. Dies bedeutet jedoch nicht, dass wir einen Variablennamen überall verwenden können, wo wir wollen. Ein Name hat auch einen Gültigkeitsbereich, 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 ist eine Liste einiger Bereiche, die während der Ausführung eines Programms vorhanden sein können.

  • Ein lokaler Bereich. Dies ist der innerste Bereich, der eine Liste der in der aktuellen Funktion verfügbaren lokalen Namen enthält.
  • Ein Umfang aller einschließenden Funktionen. Die Suche nach einem Namen beginnt mit dem nächstgelegenen 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 folgenden Abschnitten dieses Lernprogramms werden wir die eingebaute Python-Funktion dir () ausführlich verwenden, um eine Liste mit Namen im aktuellen lokalen Bereich zurückzugeben. Auf diese Weise können Sie das Konzept der Namespaces und den Geltungsbereich klarer verstehen.

Auflösung des Bereichs

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

Bevor wir anfangen, versuchen Sie es zu tippen dir () in IDLE oder einer anderen Python-IDE.

dir () # ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Alle diese Namen sind bei aufgeführt dir () sind in jedem Python-Programm verfügbar. Der Kürze halber werde ich anfangen, sie als zu bezeichnen '__builtins __'… '__spec__' in den restlichen Beispielen.

Lassen Sie uns die Ausgabe von sehen dir () Funktion nach dem Definieren einer Variablen und einer Funktion.

a_num = 10 dir () # ['__builtins __'… '__spec__', 'a_num'] def some_func (): b_num = 11 print (dir ()) some_func () # ['b_num'] dir () # ['__builtins__ '…' __Spec__ ',' a_num ',' some_func '] 

Das dir () Funktion gibt nur die Liste der Namen innerhalb des aktuellen Bereichs aus. Deshalb innerhalb der Reichweite von some_func (), Es gibt nur einen Namen b_num. Berufung dir () nach der Definition some_func () fügt es der Liste der im globalen Namespace verfügbaren Namen hinzu.

Lassen Sie uns nun die Liste der Namen in einigen verschachtelten Funktionen anzeigen. Der Code in diesem Block wird vom vorherigen Block fortgesetzt.

def outer_func (): c_num = 12 def inner_func (): d_num = 13 print (dir (), '- Namen in inner_func') e_num = 14 inner_func () print (dir (), '- Namen in outer_func') outer_func ( ) # ['d_num'] - Namen in inner_func # ['c_num', 'e_num', 'inner_func'] - Namen in outer_func

Der obige Code definiert zwei Variablen und eine Funktion innerhalb des Gültigkeitsbereichs von outer_func (). Innerhalb inner_func (), das dir () Funktion druckt nur den Namen d_num. Das scheint fair zu sein d_num ist die einzige dort definierte Variable.

Sofern nicht ausdrücklich mit angegeben global, Durch die Neuzuweisung eines globalen Namens in einem lokalen Namespace wird eine neue lokale Variable mit demselben Namen erstellt. Dies ist aus dem folgenden Code ersichtlich.

a_num = 10 b_num = 11 def outer_func (): global a_num a_num = 15 b_num = 16 def inner_func (): global a_num a_num = 20 b_num = 21 print ('a_num inside inner_func:', a_num) ', b_num) inner_func () print (' a_num in outer_func: ', a_num) print (' b_num in outer_func: ', b_num) outer_func () print (' a_num außerhalb aller Funktionen: ', a_num außerhalb von allem Funktionen: ', b_num) # a_num in inner_func: 20 # b_num in inner_func: 21 # a_num in outer_func: 20 # b_num in outer_func: 16 # a_num außerhalb aller Funktionen: 20 # b_num außerhalb aller Funktionen: 11

In beiden outer_func () und inner_func (), a_num wurde als globale Variable deklariert. Wir setzen nur einen anderen Wert für dieselbe globale Variable. Dies ist der Grund dafür, dass der Wert von a_num An allen Standorten ist es 20. Andererseits erstellt jede Funktion ihre eigene b_num Variable mit einem lokalen Bereich und der drucken() Die Funktion gibt den Wert dieser lokal begrenzten Variablen aus.

Module ordnungsgemäß importieren

Es ist üblich, externe Module in Ihre Projekte zu importieren, um die Entwicklung zu beschleunigen. Es gibt drei verschiedene Arten, Module zu importieren. In diesem Abschnitt werden Sie alle diese Methoden kennenlernen und deren Vor- und Nachteile im Detail diskutieren.

  • vom Modulimport *: 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 können auch nicht mehr feststellen, welches Modul diese Funktion tatsächlich importiert hat. Hier ist ein Beispiel für die Verwendung dieser Methode:
dir () # ['__builtins __'… '__spec__'] von math import * dir () # ['__builtins __'… '__spec__', 'acos', 'acosh', 'asin', 'asinh', # 'atan' , 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'grad', # 'e', ​​'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', # 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', # 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', # 'modf', 'nan', 'pi', 'pow', ' Radiant ',' sin ',' sinh ',' sqrt ',' tan ', #' tanh ',' trunc '] log10 (125) # 2.0969100130080562 von cmath import * dir () # [' __builtins __ '…' __spec__ ' , 'acos', 'acosh', 'asin', 'asinh', 'atan', # 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'grad', 'e', 'erf', # 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', # 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', # 'ldexp', 'lgamma', 'log', 'log10', 'log1p', ' log2 ',' modf ',' nan ',' phase ', #' pi ',' polar ',' pow ',' radians ',' re ct ',' sin ',' sinh ',' sqrt ',' tan ',' tanh ', #' trunc '] log10 (125) # (2.0969100130080562 + 0j)

Wenn Sie mit dem vertraut sind Mathematik und cmath Sie wissen bereits, dass es in beiden Modulen einige gebräuchliche Namen gibt, die jedoch für reelle und komplexe Zahlen gelten. 

Da haben wir die importiert cmath Modul nach dem Mathematik Modul überschreibt er die Funktionsdefinitionen dieser allgemeinen Funktionen aus dem Mathematik Modul. Deshalb der erste log10 (125) gibt eine reelle Zahl und die zweite zurück log10 (125) gibt eine komplexe Zahl zurück. Es gibt keine Möglichkeit, das zu verwenden log10 () Funktion jetzt aus dem Mathematikmodul. Auch wenn Sie versucht haben zu tippen math.log10 (125), Sie erhalten da eine NameError-Ausnahme Mathematik ist im Namespace nicht wirklich vorhanden.

Die Quintessenz ist, dass Sie diese Methode nicht verwenden sollten, um Funktionen aus verschiedenen Modulen zu importieren, um nur einige Tastatureingaben zu speichern.

  • vom ModulimportnamenA, NameB: Wenn Sie wissen, dass Sie nur einen oder zwei Namen aus einem Modul verwenden, können Sie sie mit dieser Methode direkt importieren. Auf diese Weise können Sie den Code präziser schreiben und dabei die Namensraumverschmutzung auf ein Minimum reduzieren. Beachten Sie jedoch, dass Sie keinen anderen Namen aus dem Modul verwenden können module.nameZ. Jede Funktion, die in Ihrem Programm denselben Namen hat, überschreibt auch die Definition der aus dem Modul importierten Funktion. Dadurch wird die importierte Funktion unbrauchbar. Hier ist ein Beispiel für die Verwendung dieser Methode:
dir () # ['__builtins __'… '__spec__'] aus math import log2, log10 dir () # ['__builtins__'… '__spec__', 'log10', 'log2'] log10 (125) # 2.0969100130080562
  • Importmodul: Dies ist die sicherste und empfohlene Art, ein Modul zu importieren. Der einzige Nachteil ist, dass Sie den Namen des Moduls allen Namen voranstellen müssen, die Sie im Programm verwenden werden. Sie können jedoch die Namensraumverschmutzung vermeiden und auch Funktionen definieren, deren Namen mit den Namen der Funktionen des Moduls übereinstimmen.
dir () # ['__builtins __'… '__spec__'] importiere math dir () # ['__builtins __'… '__spec__', 'math'] math.log10 (125) # 2.0969100130080562

Abschließende Gedanken

Ich hoffe, dieses Tutorial hat Ihnen dabei geholfen, Namespaces und deren Bedeutung zu verstehen. Sie sollten jetzt 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 Lernen zur Verfügung haben, und zögern Sie nicht, Fragen zu stellen und mit dem untenstehenden Feed wertvolles Feedback zu geben.

Im letzten Abschnitt des Artikels wurden verschiedene Möglichkeiten zum Importieren von Modulen in Python und deren Vor- und Nachteile beschrieben. Wenn Sie Fragen zu diesem Thema haben, teilen Sie mir dies bitte in den Kommentaren mit.

Lerne Python

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