Es wird empfohlen, nicht import *
in Python zu verwenden.
Kann jemand bitte den Grund dafür mitteilen, damit ich es beim nächsten Mal vermeiden kann?
import *
funktioniert nicht für mich in Python 2 oder 3.
Es wird empfohlen, nicht import *
in Python zu verwenden.
Kann jemand bitte den Grund dafür mitteilen, damit ich es beim nächsten Mal vermeiden kann?
import *
funktioniert nicht für mich in Python 2 oder 3.
Antworten:
Weil es eine Menge Dinge in Ihren Namespace bringt (möglicherweise ein anderes Objekt aus dem vorherigen Import beschattet und Sie nichts davon wissen).
Weil Sie nicht genau wissen, was importiert wird, und nicht leicht finden können, von welchem Modul eine bestimmte Sache importiert wurde (Lesbarkeit).
Weil Sie keine coolen Tools verwenden können pyflakes
, um Fehler in Ihrem Code statisch zu erkennen.
numpy.any
Schatten gebissen , any
wenn sie dies tun, from numpy import *
oder ein "hilfreiches" Tool erledigt dies für sie.
import *
die Reihenfolge der import
Anweisungen signifikant ... selbst für Standardbibliotheksmodule, denen die Importreihenfolge normalerweise egal ist . Etwas so Unschuldiges wie das Alphabetisieren Ihrer import
Aussagen könnte Ihr Drehbuch brechen, wenn ein ehemaliges Opfer des Importkrieges der einzige Überlebende wird. (Selbst wenn Ihr Skript jetzt funktioniert und sich nie ändert, kann es später plötzlich fehlschlagen, wenn das importierte Modul einen neuen Namen einführt, der einen ersetzt, auf den Sie sich verlassen haben.)
Nach dem Zen von Python :
Explizit ist besser als implizit.
... kann man damit sicher nicht streiten?
use strict
(JavaScript var
) hinzugefügt hat . Abgesehen davon ist Python natürlich nicht typenlos (es ist tatsächlich stark typisiert). Selbst wenn Sie Recht hätten, würde dies dem in dieser Antwort zitierten Zen von Python widersprechen.
Sie gehen nicht **locals()
auf Funktionen über, oder?
Da Python keine "include" -Anweisung hat und der self
Parameter explizit ist und die Gültigkeitsbereichsregeln recht einfach sind, ist es normalerweise sehr einfach, mit dem Finger auf eine Variable zu zeigen und festzustellen, woher dieses Objekt stammt - ohne andere Module zu lesen und ohne irgendeine der IDE (die ohnehin in der Art der Selbstbeobachtung begrenzt sind, weil die Sprache sehr dynamisch ist).
Das import *
bricht alles.
Es gibt auch eine konkrete Möglichkeit, Fehler zu verbergen.
import os, sys, foo, sqlalchemy, mystuff
from bar import *
Wenn das Balkenmodul eines der Attribute " os
", " mystuff
" usw. hat, überschreiben sie die explizit importierten Attribute und verweisen möglicherweise auf sehr unterschiedliche Dinge. Das Definieren __all__
in Balken ist oft sinnvoll - dies gibt an, was implizit importiert wird -, aber es ist immer noch schwierig zu verfolgen, woher Objekte kommen, ohne das Balkenmodul zu lesen und zu analysieren und seine Importe zu verfolgen . Ein Netzwerk von import *
ist das erste, was ich repariere, wenn ich die Verantwortung für ein Projekt übernehme.
Versteht mich nicht falsch: Wenn die import *
fehlen würden, würde ich weinen, um sie zu haben. Aber es muss vorsichtig verwendet werden. Ein guter Anwendungsfall besteht darin, eine Fassadenschnittstelle über einem anderen Modul bereitzustellen. Ebenso erfordert die Verwendung von bedingten Importanweisungen oder Importen in Funktions- / Klassennamensräumen ein wenig Disziplin.
Ich denke, bei mittelgroßen bis großen Projekten oder kleinen Projekten mit mehreren Mitwirkenden ist ein Minimum an Hygiene in Bezug auf die statische Analyse erforderlich - mindestens Pyflakes oder besser noch ein ordnungsgemäß konfigurierter Pylint -, um mehrere Arten von Fehlern zu erkennen sie passieren.
Da dies Python ist - zögern Sie nicht, Regeln zu brechen und zu erkunden -, aber seien Sie vorsichtig bei Projekten, die sich verzehnfachen könnten. Wenn dem Quellcode die Disziplin fehlt, ist dies ein Problem.
execfile()
. Glücklicherweise wird es selten verwendet und ist in 3.x verschwunden.
**vars()
, Globals einzuschließen, wenn sich die aufgerufene Funktion in einer anderen Datei befindet? : P
Das liegt daran, dass Sie den Namespace verschmutzen. Sie importieren alle Funktionen und Klassen in Ihren eigenen Namespace, was zu Konflikten mit den von Ihnen selbst definierten Funktionen führen kann.
Darüber hinaus denke ich, dass die Verwendung eines qualifizierten Namens für die Wartungsaufgabe klarer ist. Sie sehen in der Codezeile selbst, woher eine Funktion stammt, sodass Sie die Dokumente viel einfacher auschecken können.
Im Modul foo:
def myFunc():
print 1
In Ihrem Code:
from foo import *
def doThis():
myFunc() # Which myFunc is called?
def myFunc():
print 2
http://docs.python.org/tutorial/modules.html
Beachten Sie, dass das Importieren
*
aus einem Modul oder Paket im Allgemeinen verpönt ist, da es häufig schlecht lesbaren Code verursacht .
Angenommen, Sie haben den folgenden Code in einem Modul namens foo:
import ElementTree as etree
und dann haben Sie in Ihrem eigenen Modul:
from lxml import etree
from foo import *
Sie haben jetzt ein schwer zu debuggendes Modul, das so aussieht, als ob es lxml's etree enthält, aber stattdessen wirklich ElementTree.
Das sind alles gute Antworten. Ich werde hinzufügen, dass der Umgang mit Code in Python import *
sehr schwierig ist , wenn man neuen Leuten das Codieren beibringt . Selbst wenn Sie oder sie den Code nicht geschrieben haben, ist er immer noch ein Stolperstein.
Ich bringe Kindern (ungefähr 8 Jahre alt) bei, in Python zu programmieren, um Minecraft zu manipulieren. Ich möchte ihnen eine hilfreiche Codierungsumgebung geben, mit der sie arbeiten können ( Atom Editor ) und die REPL-gesteuerte Entwicklung (über bpython ) lehren . In Atom finde ich, dass die Hinweise / Vervollständigungen genauso effektiv funktionieren wie bpython. Glücklicherweise lässt sich Atom im Gegensatz zu einigen anderen statistischen Analysewerkzeugen nicht täuschen import *
.
Allerdings läßt dieses Beispiel nehmen ... In dieser Wrapper sie from local_module import *
ein Bündel Module einschließlich dieser Liste von Blöcken . Ignorieren wir das Risiko von Namespace-Kollisionen. Auf from mcpi.block import *
diese Weise machen sie diese gesamte Liste der obskuren Arten von Blöcken zu etwas, das Sie sich ansehen müssen, um zu wissen, was verfügbar ist. Wenn sie stattdessen verwendet hätten from mcpi import block
, könnten Sie eingeben, walls = block.
und dann würde eine Autovervollständigungsliste angezeigt.
Verstanden die gültigen Punkte, die die Leute hier setzen. Ich habe jedoch ein Argument, dass "Sternimport" manchmal nicht immer eine schlechte Praxis ist:
const.py
:
import const
, muss ich es für jede Konstante als bezeichnen const.SOMETHING
, was wahrscheinlich nicht der bequemste Weg ist.from const import SOMETHING_A, SOMETHING_B ...
, dann ist es offensichtlich viel zu ausführlich und macht den Zweck der Strukturierung zunichte.from const import *
eine bessere Wahl sein kann, a zu tun .Es ist aus zwei Gründen eine sehr schlechte Praxis:
Zu Punkt 1 : Sehen wir uns ein Beispiel dafür an:
from module1 import *
from module2 import *
from module3 import *
a = b + c - d
Hier auf dem Sehen Sie den Code nicht wird eine Idee in Bezug auf von dem Modul erhalten b
, c
undd
tatsächlich gehört.
Auf der anderen Seite, wenn Sie es mögen:
# v v will know that these are from module1
from module1 import b, c # way 1
import module2 # way 2
a = b + c - module2.d
# ^ will know it is from module2
Es ist viel sauberer für Sie und auch die neue Person, die Ihrem Team beitritt, hat eine bessere Idee.
Zu Punkt 2 : Sagen wir beides module1
und module2
haben die Variable als b
. Wenn ich es tue:
from module1 import *
from module2 import *
print b # will print the value from module2
Hier geht der Wert von module1
verloren. Es ist schwer zu debuggen, warum der Code nicht funktioniert, selbst wenn er b
in deklariert istmodule1
und ich den Code geschrieben habe, der die Verwendung meines Codes erwartetmodule1.b
Wenn Sie dieselben Variablen in verschiedenen Modulen haben und nicht das gesamte Modul importieren möchten, können Sie sogar Folgendes tun:
from module1 import b as mod1b
from module2 import b as mod2b
Als Test habe ich ein Modul test.py mit 2 Funktionen A und B erstellt, die jeweils "A 1" und "B 1" drucken. Nach dem Importieren von test.py mit:
import test
. . . Ich kann die beiden Funktionen als test.A () und test.B () ausführen, und "test" wird als Modul im Namespace angezeigt. Wenn ich also test.py bearbeite, kann ich es neu laden mit:
import importlib
importlib.reload(test)
Aber wenn ich folgendes mache:
from test import *
Es gibt keinen Verweis auf "test" im Namespace, daher gibt es keine Möglichkeit, ihn nach einer Bearbeitung neu zu laden (soweit ich das beurteilen kann), was in einer interaktiven Sitzung ein Problem darstellt. Während eine der folgenden:
import test
import test as tt
fügt "test" bzw. "tt" als Modulnamen in den Namespace ein, wodurch ein erneutes Laden möglich ist.
Wenn ich mache:
from test import *
Die Namen "A" und "B" werden im Namespace als Funktionen angezeigt . Wenn ich test.py bearbeite und den obigen Befehl wiederhole, werden die geänderten Versionen der Funktionen nicht neu geladen.
Der folgende Befehl löst eine Fehlermeldung aus.
importlib.reload(test) # Error - name 'test' is not defined
Wenn jemand weiß, wie man ein mit "from module import *" geladenes Modul neu lädt, bitte posten. Andernfalls wäre dies ein weiterer Grund, das Formular zu vermeiden:
from module import *
Wie in den Dokumenten vorgeschlagen, sollten Sie (fast) niemals import *
im Produktionscode verwenden.
Während der Import *
aus einem Modul schlecht ist, ist der Import * aus einem Paket noch schlechter. Standardmäßig werden from package import *
alle Namen importiert, die von den Paketen definiert wurden __init__.py
, einschließlich aller Submodule des Pakets, die von den vorherigen geladen wurdenimport
Anweisungen .
Wenn der __init__.py
Code eines Pakets jedoch eine Liste mit dem Namen definiert __all__
, wird davon ausgegangen, dass es sich um die Liste der Submodulnamen handelt, die importiert werden sollen, wenn sie from package import *
auftreten.
Betrachten Sie dieses Beispiel (vorausgesetzt, es ist nicht __all__
definiert in sound/effects/__init__.py
):
# anywhere in the code before import *
import sound.effects.echo
import sound.effects.surround
# in your module
from sound.effects import *
Die letzte Anweisung importiert die Module echo
und surround
in den aktuellen Namespace (möglicherweise werden vorherige Definitionen überschrieben), da sie sound.effects
bei der import
Ausführung der Anweisung im Paket definiert werden .