Ich habe versucht, einen umfassenden Leitfaden zu finden, ob es am besten ist, import module
oder from module import
? Ich habe gerade mit Python angefangen und versuche, mit Best Practices zu beginnen.
Grundsätzlich hatte ich gehofft, dass jemand seine Erfahrungen teilen könnte, welche Vorlieben andere Entwickler haben und wie man am besten Fallstricke vermeiden kann .
python
python-import
Filip Dupanović
quelle
quelle
from … import …
Syntax in Python & 'Modul importieren' vs. 'aus'from module import X,Y,Z
und'from module import *
. Letzteres verschmutzt Ihren Namespace und kann unvorhersehbare Ergebnisse liefern, je nachdem, was im Modul vor sich geht. Schlimmer noch ist esfrom module import *
mit mehreren Modulen.Antworten:
Der Unterschied zwischen
import module
undfrom module import foo
ist hauptsächlich subjektiv. Wählen Sie die aus, die Ihnen am besten gefällt, und verwenden Sie sie konsequent. Hier sind einige Punkte, die Ihnen bei der Entscheidung helfen sollen.import module
import
Aussagen. Sie müssen keine zusätzlichen Importe hinzufügen, um ein anderes Element aus dem Modul zu verwendenmodule.foo
Ihres Codes kann mühsam und redundant sein (Langeweile kann durch dieimport module as mo
anschließende Eingabe minimiert werdenmo.foo
).from module import foo
foo
import
Anweisung aktualisierenfoo
. Zum Beispiel ist es weniger klar, wasceil()
im Vergleich zu tutmath.ceil()
Beide Methoden sind akzeptabel, werden jedoch nicht verwendet
from module import *
.Wenn Sie einen vernünftig großen Code-Satz
import *
wahrscheinlich in das Modul zementieren, kann er nicht entfernt werden. Dies liegt daran, dass es schwierig ist zu bestimmen, welche im Code verwendeten Elemente vom 'Modul' stammen, was es einfach macht, an den Punkt zu gelangen, an dem Sie glauben, dass Sie das nichtimport
mehr verwenden, aber es ist äußerst schwierig, sicher zu sein.quelle
from module import *
kann besonders nützlich sein, wenn Sie es verwenden als :if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *
. Dann kann Ihr übergeordnetes Modul möglicherweise betriebssystemunabhängige Funktionsnamen enthalten, wenn die Funktionsnamen in module_lin & module_win dieselben Namen haben. Es ist, als würde man eine Klasse bedingt erben.Es gibt hier ein weiteres Detail, das nicht erwähnt wird und sich auf das Schreiben in ein Modul bezieht. Zugegeben, das ist vielleicht nicht sehr häufig, aber ich habe es von Zeit zu Zeit gebraucht.
Aufgrund der Funktionsweise von Referenzen und Namensbindung in Python müssen Sie foo a importieren, wenn Sie ein Symbol in einem Modul, z. B. foo.bar, von außerhalb dieses Moduls aktualisieren und einen anderen Importcode haben möchten, der diese Änderung "sieht" bestimmte Weise. Zum Beispiel:
Modul foo:
Modul a:
Modul b:
Wenn Sie jedoch Symbolnamen anstelle von Modulnamen importieren, funktioniert dies nicht.
Wenn ich dies beispielsweise in Modul a mache:
Kein Code außerhalb von a sieht die Leiste als "Orangen", da meine Einstellung der Leiste lediglich den Namen "Leiste" innerhalb des Moduls a beeinflusste, nicht in das foo-Modulobjekt "griff" und dessen "Leiste" aktualisierte.
quelle
Obwohl viele Leute bereits über
import
vs erklärt habenimport from
, möchte ich versuchen, ein bisschen mehr darüber zu erklären, was unter der Haube passiert und wo sich all die Orte befinden, an denen es sich ändert.import foo
::Importiert
foo
und erstellt einen Verweis auf dieses Modul im aktuellen Namespace. Anschließend müssen Sie den abgeschlossenen Modulpfad definieren, um aus dem Modul heraus auf ein bestimmtes Attribut oder eine bestimmte Methode zugreifen zu können.ZB
foo.bar
aber nichtbar
from foo import bar
::Importiert
foo
und erstellt Verweise auf alle aufgelisteten Mitglieder (bar
). Setzt die Variable nichtfoo
.ZB
bar
aber nichtbaz
oderfoo.baz
from foo import *
::Importiert
foo
und erstellt Verweise auf alle öffentlichen Objekte, die von diesem Modul im aktuellen Namespace definiert wurden (alles, was in vorhanden ist,__all__
falls__all__
vorhanden, sonst alles, was nicht beginnt_
). Setzt die Variable nichtfoo
.ZB
bar
undbaz
aber nicht_qux
oderfoo._qux
.Nun wollen wir sehen, wann wir es tun
import X.Y
:Überprüfen Sie
sys.modules
mit Namenos
undos.path
:Check
globals()
undlocals()
Namespace diktieren mitos
undos.path
:Aus dem obigen Beispiel haben wir herausgefunden, dass nur
os
in den lokalen und globalen Namespace eingefügt wird. Wir sollten also in der Lage sein:Aber nicht
path
.Sobald Sie das Löschen
os
von Einheimischen () Namespace, werden Sie nicht zugreifen könnenos
, sowieos.path
auch wenn sie in sys.modules existieren:Sprechen wir jetzt über
import from
:from
::Überprüfen Sie
sys.modules
mitos
undos.path
:Wir fanden, dass
sys.modules
wir in das gleiche wie zuvor gefunden haben, indem wir verwendet habenimport name
OK, lassen Sie uns überprüfen, wie es in
locals()
undglobals()
Namespace-Diktaten aussieht :Sie können mit dem Namen zugreifen,
path
nicht mitos.path
:Löschen wir 'Pfad' aus
locals()
:Ein letztes Beispiel mit einem Alias:
Und kein Pfad definiert:
quelle
as SYMBOL
dieser Antwort überhaupt?Beide Möglichkeiten werden aus einem Grund unterstützt: Es gibt Zeiten, in denen eine angemessener ist als die andere.
import module
: schön, wenn Sie viele Bits aus dem Modul verwenden. Nachteil ist, dass Sie jede Referenz mit dem Modulnamen qualifizieren müssen.from module import ...
: schön, dass importierte Elemente direkt ohne Modulnamenpräfix verwendet werden können. Der Nachteil ist, dass Sie jedes Objekt auflisten müssen, das Sie verwenden, und dass im Code nicht klar ist, woher etwas stammt.Welche zu verwenden ist, hängt davon ab, welche den Code klar und lesbar macht und hat mehr als ein wenig mit persönlichen Vorlieben zu tun. Ich neige
import module
allgemein dazu, weil im Code sehr klar ist, woher ein Objekt oder eine Funktion stammt. Ich verwende ,from module import ...
wenn ich einige Objekt / Funktion unter Verwendung einer Menge im Code.quelle
from M import X
die Qualifikationsmerkmale irgendwie zu nutzen und trotzdem zu nutzen ? Es scheint, dass Sie das Beste aus beiden Welten bekommen könnten, wenn Sie esM.X
nach diesem Import noch tun könnten .class m: from something.too.long import x, y, z
. Würde das aber nicht wirklich empfehlen.Ich persönlich benutze immer
und dann auf alles zugreifen als
usw. Der Grund dafür ist, dass Sie gleichzeitig einen kurzen Aufruf haben und den Modul-Namespace jeder Routine klar definieren. Dies ist sehr nützlich, wenn Sie nach der Verwendung eines bestimmten Moduls in Ihrer Quelle suchen müssen.
Verwenden Sie den Import * natürlich nicht, da er Ihren Namespace verschmutzt und Ihnen nicht sagt, woher eine bestimmte Funktion kommt (von welchem Modul).
Natürlich können Probleme auftreten, wenn Sie denselben Modulnamen für zwei verschiedene Module in zwei verschiedenen Paketen haben, z
In diesem Fall stoßen Sie natürlich auf Probleme, aber dann gibt es einen starken Hinweis darauf, dass Ihr Paketlayout fehlerhaft ist, und Sie müssen es überdenken.
quelle
Ist am besten, wenn Sie viele Funktionen aus dem Modul verwenden.
Dies ist am besten geeignet, wenn Sie vermeiden möchten, den globalen Namespace mit allen Funktionen und Typen eines Moduls zu verschmutzen, wenn Sie dies nur benötigen
function
.quelle
Ich habe gerade einen subtileren Unterschied zwischen diesen beiden Methoden entdeckt.
Wenn das Modul
foo
einen folgenden Import verwendet:Dann
bar
kann das Modul versehentlich so verwendet werden,count
als wäre es definiert infoo
, nicht initertools
:Wenn
foo
verwendet:Der Fehler ist immer noch möglich, aber weniger wahrscheinlich.
bar
muss:Dies verursachte mir einige Probleme. Ich hatte ein Modul, das versehentlich eine Ausnahme von einem Modul importierte, das es nicht definierte, sondern nur von einem anderen Modul importierte (mit
from module import SomeException
). Wenn der Import nicht mehr benötigt und entfernt wurde, war das fehlerhafte Modul defekt.quelle
Hier ist ein weiterer Unterschied nicht erwähnt. Dies wird wörtlich von http://docs.python.org/2/tutorial/modules.html kopiert
Beachten Sie dies bei der Verwendung
Das Element kann entweder ein Submodul (oder ein Subpaket) des Pakets oder ein anderer im Paket definierter Name sein, z. B. eine Funktion, eine Klasse oder eine Variable. Die import-Anweisung testet zunächst, ob das Element im Paket definiert ist. Andernfalls wird davon ausgegangen, dass es sich um ein Modul handelt, und es wird versucht, es zu laden. Wenn es nicht gefunden wird, wird eine ImportError-Ausnahme ausgelöst.
Im Gegensatz dazu, wenn Syntax wie
Jeder Artikel mit Ausnahme des letzten muss ein Paket sein. Das letzte Element kann ein Modul oder ein Paket sein, kann jedoch keine Klasse, Funktion oder Variable sein, die im vorherigen Element definiert wurde.
quelle
Da ich auch Anfänger bin, werde ich versuchen, dies auf einfache Weise zu erklären: In Python gibt es drei Arten von
import
Anweisungen:1. Generische Importe:
Diese Art des Imports ist mein persönlicher Favorit. Der einzige Nachteil dieser Importtechnik ist, dass Sie die folgende Syntax verwenden müssen, wenn Sie die Funktion eines Moduls verwenden müssen:
Natürlich erhöht es den Schreibaufwand, aber als Anfänger hilft es Ihnen, den Überblick über das Modul und die damit verbundenen Funktionen zu behalten (ein guter Texteditor reduziert den Schreibaufwand erheblich und wird empfohlen).
Mit dieser Importanweisung kann der Schreibaufwand weiter reduziert werden:
Jetzt können Sie anstelle von
math.sqrt()
verwendenm.sqrt()
.2. Funktionsimporte:
Diese Art des Imports eignet sich am besten, wenn Ihr Code nur auf einzelne oder wenige Funktionen des Moduls zugreifen muss. Um jedoch ein neues Element aus dem Modul zu verwenden, müssen Sie die Importanweisung aktualisieren.
3. Universalimporte:
Dies reduziert zwar den Schreibaufwand erheblich, wird jedoch nicht empfohlen, da Ihr Code mit verschiedenen Funktionen des Moduls gefüllt wird und deren Name mit dem Namen der benutzerdefinierten Funktionen in Konflikt stehen kann. Beispiel:
Wenn Sie eine eigene Funktion namens sqrt haben und Mathematik importieren, ist Ihre Funktion sicher: Es gibt Ihre Funktion sqrt und math.sqrt. Wenn Sie aus Mathe importieren *, haben Sie jedoch ein Problem: nämlich zwei verschiedene Funktionen mit genau demselben Namen. Quelle: Codecademy
quelle
Bei
import
muss das Token ein Modul (eine Datei mit Python-Befehlen) oder ein Paket (ein Ordnersys.path
mit einer Datei__init__.py
) sein.Wenn es Unterpakete gibt:
die Voraussetzungen für Ordner (Paket) oder Datei (Modul) sind die gleichen, aber die Ordner oder die Datei muss im Inneren sein ,
package2
die im Inneren sein müssenpackage1
, und beidepackage1
undpackage2
enthalten__init__.py
Dateien. https://docs.python.org/2/tutorial/modules.htmlMit dem
from
Importstil:Das Paket oder Modul gibt den Namespace der Datei, die die
import
Anweisung enthält, alsmodule
(oderpackage
) anstelle von einpackage1.package2.module
. Sie können jederzeit an einen bequemeren Namen binden:Nur der
from
Importstil ermöglicht es Ihnen, eine bestimmte Funktion oder Variable zu benennen:ist erlaubt, aber
ist nicht erlaubt.
quelle
Um das zu ergänzen, was die Leute gesagt haben
from x import *
: Abgesehen davon, dass es schwieriger ist zu sagen, woher die Namen stammen, werden Codeprüfer wie Pylint abgeworfen. Sie melden diese Namen als undefinierte Variablen.quelle
Meine eigene Antwort darauf hängt hauptsächlich davon ab, wie viele verschiedene Module ich verwenden werde. Wenn ich nur ein oder zwei verwenden werde, werde ich oft
from
... verwenden,import
da es im Rest der Datei weniger Tastenanschläge gibt, aber wenn ich viele verschiedene Module verwenden möchte, bevorzuge ich nurimport
denn das bedeutet, dass jede Modulreferenz selbstdokumentierend ist. Ich kann sehen, woher jedes Symbol kommt, ohne herumjagen zu müssen.Normalerweise bevorzuge ich den selbstdokumentierenden Stil des einfachen Imports und wechsle nur von .. import, wenn die Häufigkeit, mit der ich den Modulnamen eingeben muss, über 10 bis 20 steigt, selbst wenn nur ein Modul importiert wird.
quelle
Einer der signifikanten Unterschied fand ich heraus , die überraschend niemand darüber gesprochen hat , ist die Ebene mit Import Sie zugreifen können
private variable
undprivate functions
aus dem importierten Modul, das nicht möglich ist , aus-Import - Anweisung.Code im Bild:
settings.py
plain_importer.py
from_importer.py
quelle
Modul importieren - Sie benötigen keine zusätzlichen Anstrengungen, um eine andere Sache aus dem Modul abzurufen. Es hat Nachteile wie redundante Typisierung
Modulimport von - Weniger Eingabe und mehr Kontrolle darüber, auf welche Elemente eines Moduls zugegriffen werden kann. Um ein neues Element aus dem Modul zu verwenden, müssen Sie Ihre Importanweisung aktualisieren.
quelle
Es gibt einige eingebaute Module, die hauptsächlich nackte Funktionen enthalten ( base64 , math , os , shutil , sys , time , ...), und es ist definitiv eine gute Praxis, diese nackten Funktionen an einen Namespace zu binden und so die Lesbarkeit Ihrer zu verbessern Code. Überlegen Sie, wie schwierig es ist, die Bedeutung dieser Funktionen ohne ihren Namespace zu verstehen:
als wenn sie an ein Modul gebunden sind:
Manchmal benötigen Sie sogar den Namespace, um Konflikte zwischen verschiedenen Modulen zu vermeiden ( json.load vs. pickle.load ).
Auf der anderen Seite gibt es einige Module, die hauptsächlich Klassen enthalten ( configparser , datetime , tempfile , zipfile , ...), und viele von ihnen machen ihre Klassennamen selbsterklärend genug:
Daher kann es zu einer Debatte kommen, ob die Verwendung dieser Klassen mit dem zusätzlichen Modul-Namespace in Ihrem Code neue Informationen hinzufügt oder nur den Code verlängert.
quelle
Ich möchte noch hinzufügen, dass bei den Importaufrufen Folgendes zu beachten ist:
Ich habe folgende Struktur:
main.py:
dis.dis zeigt den Unterschied:
Am Ende sehen sie gleich aus (STORE_NAME ist das Ergebnis in jedem Beispiel), aber dies ist erwähnenswert, wenn Sie die folgenden vier zirkulären Importe berücksichtigen müssen:
Beispiel 1
Das funktioniert
Beispiel2
Kein Würfel
Beispiel3
Ähnliches Problem ... aber eindeutig von x import y ist nicht dasselbe wie import import xy wie y
Beispiel4
Dieser funktioniert auch
quelle
Dies ist meine Verzeichnisstruktur meines aktuellen Verzeichnisses:
Die
import
Anweisung merkt sich alle Zwischennamen .Diese Namen müssen qualifiziert sein:
Die
from ... import ...
Anweisung merkt sich nur den importierten Namen .Dieser Name darf nicht qualifiziert sein:
quelle
Wie Jan Wrobel erwähnt, besteht ein Aspekt der verschiedenen Importe darin, wie die Importe offengelegt werden.
Modul mymath
Verwendung von Mymath :
Wenn ich
gcd
nur für den internen Gebrauch importiert habe , um es nicht an Benutzer von weiterzugebenmymath
, kann dies unpraktisch sein. Ich habe das ziemlich oft und in den meisten Fällen möchte ich "meine Module sauber halten".Abgesehen von dem Vorschlag von Jan Wrobel , dies durch die Verwendung von etwas mehr zu verschleiern
import math
, habe ich begonnen, Importe vor der Offenlegung zu verbergen, indem ich einen führenden Unterstrich verwendete:In größeren Projekten kann ich mit dieser "Best Practice" genau steuern, was bei nachfolgenden Importen angegeben wird und was nicht. Dies hält meine Module sauber und zahlt sich bei einer bestimmten Projektgröße aus.
quelle