Python: Warum kann ein importiertes Modul nicht auf ein anderes importiertes Modul verweisen?

10

main.py:

%Vor%

subone.py:

%Vor%

subtw.py:

%Vor%

Running python main.py löst eine NameError: name 'subone' is not defined aus. Ich habe erwartet, dass es "abc" druckt.

Das Refactoring für die Verwendung von from import und Klassen hilft nicht:

main.py:

%Vor%

subone.py:

%Vor%

subtw.py:

%Vor%

ABER es wird von main.py: def 'drucken. (Dies funktioniert auch, wenn import verwendet wird.)

Warum funktioniert das so? Es scheint, als ob subone importiert wird, sollte es für subtwo verfügbar sein.

Liegt es daran, dass importierte Module voneinander abhängig sind, ohne dass sie ihr "Eltern" -Modul durchlaufen müssen? Gibt es einen anderen, üblichen Weg, dies zu tun?

Aktualisierung:

Ich verstehe jetzt, dass das erste Beispiel nicht funktionieren wird, weil die Zeile print subone.a den Namen subone nicht erkennt, obwohl sie nicht im subtwo s Namespace ist in main.py 's) und wird innerhalb des Moduls subtwo aufgerufen. Dies kann behoben werden, indem import subone am Anfang von subtwo.py verwendet wird - es lädt das Modul nicht neu, sondern fügt es dem% code%% namespace hinzu, so dass subtwo es benutzen kann.

Aber was ist damit:

main.py:

%Vor%

subone.py:

%Vor%

subtw.py:

%Vor%

Ich würde denken, dass, da subtwo und Wrap beide direkt in den Namespace von Nugget geladen werden, sie den Namespace von main benutzen und sich gegenseitig referenzieren können, aber ein% wirft Code%. IS IT, weil main von im Namespace NameError: name 'Nugget' is not defined vor dem Laden in den Namespace von Wrap ausgewertet / überprüft wird?

    
William Linton 11.10.2010, 18:40
quelle

5 Antworten

6

Wenn Sie Ihre subtw.py so geändert haben, funktioniert es

%Vor%

Wenn Sie in subtwo.py subone.a verwenden, versuchen Sie, auf den Namespace subone in subtwo.py zuzugreifen, und im Namespace "subone" sollte ein Attribut "a" vorhanden sein.

Wenn Sie subone in subwoo.py importieren, wird Subone zum Namespace hinzugefügt und subone Namespace hat das Attribut a. also wird subone.a funktionieren.

Ich würde auch vorschlagen, dass Sie mit dir () spielen, um zu sehen, wie Namespaces hinzugefügt werden.

In subtw.py können Sie Folgendes tun:

%Vor%

Versuchen Sie auch, "print dir ()" vor und nach Ihren Importanweisungen hinzuzufügen, und die Idee sollte Ihnen klar werden.

  

"import x" fügt 'x' zu den aktuellen Modulen hinzu   Namespace während "von x importieren *" wird   Fügen Sie alle Attribute auf Modulebene hinzu   direkt in den aktuellen Modulnamensraum

In Ihrem obigen ersten Beispiel von main.py, subone.py und subtwo.py enthält der Namespace in main.py "subone" und "subtwo", während subtwo.py einen leeren Namespace und kann nicht auf subone.a zugreifen.

[Bearbeiten: Einige weitere Erklärungen] Betrachten Sie folgende Dateien: main.py

%Vor%

subone.py

%Vor%

subtw.py

%Vor%

Und die Ausgabe von laufendem main.py:

%Vor%
  

Einige Beobachtungen

  1. Sie werden feststellen, dass beim Importieren eines Moduls subtw.py die print-Anweisung sofort ausgeführt wird.
  2. Wenn also subone und subtwo in main.py importiert werden, wird der Namespace von main.py erweitert.
  3. Das bedeutet nicht, dass der Namespace von subtwo erweitert wird. So ist "a" nur in main.py über subone.a
  4. verfügbar
  5. Wenn wir subone in subtwo.py importieren, dann wird der Namespace von subtwo mit subone erweitert und das Attribut a des Moduls subone steht in subotow.py über subone.a
  6. zur Verfügung
pyfunc 11.10.2010, 18:45
quelle
3

Können Sie erklären, warum Sie subone subone haben sollten, wenn subone von main importiert wurde? So kann subtwo.py kompiliert werden, ohne zu wissen, was main.py importiert hat.

Wenn ein zweites Programm subtw.py importiert, hängt das subwoo-Wissen über subone davon ab, welches der beiden Hauptprogramme unterzulegen ist? Dies würde die Wiederverwendbarkeit von unter zwei reduzieren.

Es scheint, als ob Sie die Kompilierung als einen Prozess mit einer definierten Reihenfolge betrachten, die Zustandsinformationen akkumuliert: compile main.py, währenddessen wir subone.py kompilieren / importieren, Informationen daraus sammeln und dann kompilieren / Importieren Sie subtw.py, indem Sie die Informationen verwenden, die wir bereits gesammelt haben.

Stattdessen ist die Kompilierung jedes Moduls unabhängig von anderen, sofern keine Abhängigkeiten deklariert sind. Dies macht die Wiederverwendung und Pflege von Code wesentlich einfacher: Es gibt weniger versteckte Abhängigkeiten.

  

Liegt es daran, dass es schlecht programmiert ist?   importierte Module hängen von jedem ab   andere ohne durch ihre zu gehen   'Eltern' Modul?

Nicht als solches ... Es ist einfach eine schlechte Programmierung, Modul 2 von Modul 1 abhängig zu machen, ohne es zu sagen , d. h. ohne Modul 2 zu deklarieren "Ich bin von Modul 1 abhängig".

    
LarsH 11.10.2010 18:45
quelle
2

Der subtwo -Namespace ist komplett leer, es sei denn, Sie importieren subone in ihn.

Was Programmierpraktiken angeht, können subone und subtwo voneinander abhängig sein, wenn Sie dies wünschen, Sie müssen sie nur explizit verlinken (mit einem import )

    
Nick T 11.10.2010 18:43
quelle
0

Was Ihr zweites Beispiel betrifft, weiß "main.py" über Nugget , aber "subtwo.py" nicht.

Ich denke, es würde helfen, so darüber nachzudenken. Jedes Modul (Datei) muss so funktionieren, als wären nur die anderen Module vorhanden, die es importiert. In diesem Fall könnte "subtwo.py" nicht von selbst ausgeführt werden, da Nugget nicht importiert wurde. Im Wesentlichen weiß "subtwo.py" nicht, was "main.py" weiß. Es sollte nicht, weil es von irgendwoher von irgendwem aufgerufen werden kann, und es kann sich nicht darauf verlassen, dass jemand anderes das Zeug importiert, das es braucht.

    
Davy8 11.10.2010 20:42
quelle
0

Dies liegt daran, dass die importierten Module eigene Namespaces haben. Was du geschrieben hast ist sehr ähnlich wie:

%Vor%

Die Module haben ihre Namespaces lokal, und wenn Sie from subone import * verwenden, importieren Sie den Namespace NUR in main.py Namespace, auf den von subtwo nicht zugegriffen werden kann.

Trotzdem - was Sie versuchen, ist eine sehr schlechte Übung. Vermeiden Sie globale Variablen und import * , nur weil Sie mehr und mehr verwirrt werden, wie jetzt.

Mehr dazu: Ссылка

Ссылка

Ссылка

und vielleicht: Ссылка

    
Śmigło 19.12.2017 10:13
quelle

Tags und Links