Ich bin ein wenig verwirrt über die Vielzahl von Möglichkeiten, wie Sie Module in Python importieren können.
import X
import X as Y
from A import B
Ich habe über Scoping und Namespaces gelesen, möchte aber einige praktische Ratschläge dazu, welche Strategie unter welchen Umständen und warum die beste ist. Sollten Importe auf Modulebene oder auf Methoden- / Funktionsebene erfolgen? Im __init__.py
oder im Modulcode selbst?
Meine Frage wird von " Python-Pakete - Import nach Klasse, nicht Datei " nicht wirklich beantwortet , obwohl sie offensichtlich verwandt ist.
python
python-import
Simon
quelle
quelle
Antworten:
Im Produktionscode unseres Unternehmens versuchen wir, die folgenden Regeln zu befolgen.
Wir platzieren Importe am Anfang der Datei, direkt nach der Dokumentzeichenfolge der Hauptdatei, z.
""" Registry related functionality. """ import wx # ...
Wenn wir nun eine Klasse importieren, die eine der wenigen im importierten Modul ist, importieren wir den Namen direkt, sodass wir im Code nur den letzten Teil verwenden müssen, z.
from RegistryController import RegistryController from ui.windows.lists import ListCtrl, DynamicListCtrl
Es gibt jedoch Module, die Dutzende von Klassen enthalten, z. B. eine Liste aller möglichen Ausnahmen. Dann importieren wir das Modul selbst und verweisen im Code darauf:
from main.core import Exceptions # ... raise Exceptions.FileNotFound()
Wir verwenden das
import X as Y
so selten wie möglich, da es die Suche nach der Verwendung eines bestimmten Moduls oder einer bestimmten Klasse erschwert. Manchmal müssen Sie es jedoch verwenden, wenn Sie zwei Klassen importieren möchten, die denselben Namen haben, aber in verschiedenen Modulen vorhanden sind, z.from Queue import Queue from main.core.MessageQueue import Queue as MessageQueue
In der Regel führen wir keine Importe innerhalb von Methoden durch - sie machen Code einfach langsamer und weniger lesbar. Einige mögen dies als einen guten Weg betrachten, um das Problem der zyklischen Importe leicht zu lösen, aber eine bessere Lösung ist die Code-Reorganisation.
quelle
Lassen Sie mich nur einen Teil des Gesprächs in die von Guido van Rossum gestartete Django-Dev-Mailingliste einfügen:
Quelle: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
quelle
Ich würde normalerweise
import X
auf Modulebene verwenden. Wenn Sie nur ein einzelnes Objekt aus einem Modul benötigen, verwenden Siefrom X import Y
.Nur verwenden,
import X as Y
wenn Sie anderweitig mit einem Namenskonflikt konfrontiert sind.Ich verwende Importe nur auf Funktionsebene, um Dinge zu importieren, die ich benötige, wenn das Modul als Hauptmodul verwendet wird, wie zum Beispiel:
def main(): import sys if len(sys.argv) > 1: pass
HTH
quelle
Jemand oben hat das gesagt
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
ist äquivalent zu
import X
import X
Ermöglicht direkte Änderungen am AP, währendfrom X import ...
Kopien des AP erstellt werden. Dennfrom X import A..P
Sie erhalten keine Aktualisierungen von Variablen, wenn diese geändert werden. Wenn Sie sie ändern, ändern Sie nur Ihre Kopie, aber X kennt Ihre Änderungen.Wenn AP Funktionen sind, kennen Sie den Unterschied nicht.
quelle
mock
in Unit-Tests beispielsweise zum Verspotten verwenden möchten,X.A
funktioniert dies nur, wenn Sie es verwendet habenimport X
.Andere haben hier den größten Teil des Bodens abgedeckt, aber ich wollte nur einen Fall hinzufügen, den ich
import X as Y
(vorübergehend) verwenden werde, wenn ich eine neue Version einer Klasse oder eines Moduls ausprobiere.Wenn wir also auf eine neue Implementierung eines Moduls migrieren, aber die Codebasis nicht auf einmal aufteilen möchten, schreiben wir möglicherweise ein
xyz_new
Modul und tun dies in den von uns migrierten Quelldateien:import xyz_new as xyz
Sobald wir die gesamte Codebasis gekürzt haben, ersetzen wir einfach das
xyz
Modul durchxyz_new
und ändern alle Importe wieder aufimport xyz
quelle
Tu das NICHT:
from X import *
es sei denn, Sie sind absolut sicher, dass Sie alles in diesem Modul verwenden werden. Und selbst dann sollten Sie wahrscheinlich einen anderen Ansatz wählen.
Davon abgesehen ist es nur eine Frage des Stils.
from X import Y
ist gut und erspart Ihnen viel Tippen. Ich benutze das normalerweise, wenn ich etwas ziemlich häufig darin verwende. Wenn Sie jedoch viel aus diesem Modul importieren, kann dies zu einer Importanweisung führen, die folgendermaßen aussieht:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
Du hast die Idee. Das ist, wenn Importe mögen
import X
nützlich werden. Entweder das oder wenn ich in X nicht wirklich häufig etwas benutze.
quelle
Ich versuche im Allgemeinen, das reguläre zu verwenden
import modulename
, es sei denn, der Modulname ist lang oder wird häufig verwendet.Zum Beispiel würde ich tun ..
from BeautifulSoup import BeautifulStoneSoup as BSS
..so kann ich
soup = BSS(html)
statt tunBeautifulSoup.BeautifulStoneSoup(html)
Oder..
from xmpp import XmppClientBase
.. anstatt den gesamten xmpp zu importieren, wenn ich nur die XmppClientBase verwende
Die Verwendung
import x as y
ist praktisch, wenn Sie entweder sehr lange Methodennamen importieren oder verhindern möchten, dass ein vorhandener Import / eine Variable / eine Klasse / eine Methode überlastet wird (etwas, das Sie vollständig vermeiden sollten, das aber nicht immer möglich ist).Angenommen, ich möchte eine main () - Funktion von einem anderen Skript aus ausführen, habe aber bereits eine main () - Funktion.
from my_other_module import main as other_module_main
..wollte meine
main
Funktion nicht durch my_other_module's ersetzenmain
Oh, eine Sache - tu es nicht
from x import *
- es macht deinen Code sehr schwer zu verstehen, da du nicht leicht erkennen kannst, woher eine Methode stammt (from x import *; from y import *; my_func()
- wo ist my_func definiert?)In allen Fällen könnten Sie einfach tun
import modulename
und dann tunmodulename.subthing1.subthing2.method("test")
...Das
from x import y as z
Zeug dient nur der Bequemlichkeit - verwenden Sie es, wenn es Ihren Code leichter lesen oder schreiben lässt!quelle
xmpp
oderXmppClientBase
. Diese Begründung ist also nicht gültigas
nur einen Modul- / Objektnamen zu verkürzen. Woher kommtBSS()
das? Die Verwendungfrom
leidet auch (ein bisschen) darunter :from mymod import MyClass
. Jetzt 300 Zeilen vorausclass MyOtherClass(MyClass):
... sehen Sie , woher kam MyClass wieder? Ein Leser ist gezwungen, immer zum Header zurückzukehren, um zu überprüfen, woher welches Objekt importiert wurdeWenn Sie eine gut geschriebene Bibliothek haben, was in Python manchmal der Fall ist, sollten Sie sie einfach importieren und als solche verwenden. Eine gut geschriebene Bibliothek nimmt in der Regel das eigene Leben und die eigene Sprache in Anspruch, was zu einem angenehm zu lesenden Code führt, in dem Sie selten auf die Bibliothek verweisen. Wenn eine Bibliothek gut geschrieben ist, sollten Sie nicht zu oft umbenennen oder etwas anderes.
import gat node = gat.Node() child = node.children()
Manchmal ist es nicht möglich, es so zu schreiben, oder Sie möchten Dinge aus der importierten Bibliothek entfernen.
from gat import Node, SubNode node = Node() child = SubNode(node)
Manchmal tun Sie dies für viele Dinge, wenn Ihre Importzeichenfolge 80 Spalten überläuft. Es ist eine gute Idee, dies zu tun:
from gat import ( Node, SubNode, TopNode, SuperNode, CoolNode, PowerNode, UpNode )
Die beste Strategie besteht darin, alle diese Importe oben in der Datei zu belassen. Vorzugsweise alphabetisch sortiert, zuerst Import-Anweisungen, dann aus Import-Anweisungen.
Jetzt sage ich Ihnen, warum dies die beste Konvention ist.
Python hätte durchaus einen automatischen Import haben können, der anhand der Hauptimporte nach dem Wert sucht, wenn er nicht im globalen Namespace gefunden werden kann. Das ist aber keine gute Idee. Ich erkläre kurz warum. Abgesehen davon, dass die Implementierung komplizierter ist als der einfache Import, würden Programmierer nicht so sehr über die Abhängigkeiten nachdenken und herausfinden, von wo Sie Dinge importiert haben, sondern auf andere Weise als nur über Importe nachdenken.
Die Notwendigkeit, Abhängigkeiten herauszufinden, ist ein Grund, warum Menschen "von ... import *" hassen. Es gibt jedoch einige schlechte Beispiele, bei denen Sie dies tun müssen, zum Beispiel opengl-Wrappings.
Die Importdefinitionen sind also tatsächlich wertvoll, um die Abhängigkeiten des Programms zu definieren. Auf diese Weise sollten Sie sie ausnutzen. Von ihnen aus können Sie schnell überprüfen, woher eine seltsame Funktion importiert wird.
quelle
Dies
import X as Y
ist nützlich, wenn Sie unterschiedliche Implementierungen desselben Moduls / derselben Klasse haben.Mit einigen verschachtelten
try..import..except ImportError..import
s können Sie die Implementierung vor Ihrem Code verbergen. Siehe Beispiel für den Import von lxml etree :try: from lxml import etree print("running with lxml.etree") except ImportError: try: # Python 2.5 import xml.etree.cElementTree as etree print("running with cElementTree on Python 2.5+") except ImportError: try: # Python 2.5 import xml.etree.ElementTree as etree print("running with ElementTree on Python 2.5+") except ImportError: try: # normal cElementTree install import cElementTree as etree print("running with cElementTree") except ImportError: try: # normal ElementTree install import elementtree.ElementTree as etree print("running with ElementTree") except ImportError: print("Failed to import ElementTree from any known place")
quelle
Ich bin mit Jason in der Tatsache, nicht zu verwenden
from X import *
Aber in meinem Fall (ich bin kein erfahrener Programmierer, daher entspricht mein Code nicht so gut dem Codierungsstil) mache ich in meinen Programmen normalerweise eine Datei mit allen Konstanten wie Programmversion, Autoren, Fehlermeldungen und all dem Zeug. Die Datei sind also nur Definitionen, dann mache ich den Import
from const import *
Das spart mir viel Zeit. Aber es ist die einzige Datei, die diesen Import hat, und das liegt daran, dass alle in dieser Datei nur Variablendeklarationen sind.
Diese Art des Imports in eine Datei mit Klassen und Definitionen kann nützlich sein, aber wenn Sie diesen Code lesen müssen, verbringen Sie viel Zeit damit, Funktionen und Klassen zu finden.
quelle