Sei from module import function
der FMIF-Codierungsstil.
Nennen import module
wir den IM-Codierungsstil.
Nennen from package import module
wir den FPIM-Codierungsstil.
Warum wird IM + FPIM als besserer Codierungsstil als FMIF angesehen? (In diesem Beitrag finden Sie die Inspiration für diese Frage.)
Hier sind einige Kriterien, die mich dazu veranlassen, FMIF IM vorzuziehen:
- Kürze des Codes: Es ermöglicht mir, kürzere Funktionsnamen zu verwenden und so die Konvention von 80 Spalten pro Zeile einzuhalten.
- Lesbarkeit:
chisquare(...)
erscheint besser lesbar alsscipy.stats.stats.chisquare(...)
. Obwohl dies ein subjektives Kriterium ist, denke ich, dass die meisten Menschen zustimmen würden. - Einfache Umleitung: Wenn ich FMIF verwenden und aus irgendeinem Grunde zu einem späteren Zeitpunkt will Python umleiten zu definieren ,
function
ausalt_module
stattmodule
Ich brauche nur eine Zeile zu ändern:from alt_module import function
. Wenn ich IM verwenden würde, müsste ich viele Codezeilen ändern.
Ich interessiere mich für alle Gründe, warum IM + FPIM besser als FMIF ist, aber insbesondere würde ich mich für die Ausarbeitung der folgenden hier genannten Punkte interessieren :
Vorteile für IM:
- Leichtes Verspotten / Injizieren in Tests. (Ich bin mit Spott nicht sehr vertraut, obwohl ich kürzlich erfahren habe, was der Begriff bedeutet. Können Sie Code anzeigen, der zeigt, wie IM hier besser ist als FMIF?)
- Möglichkeit für ein Modul, sich durch Neudefinition einiger Einträge flexibel zu ändern. (Ich muss etwas falsch verstehen, denn dies scheint ein Vorteil von FMIF gegenüber IM zu sein. Siehe meinen dritten Grund für FMIF oben.)
- vorhersehbares und kontrollierbares Verhalten bei der Serialisierung und Wiederherstellung Ihrer Daten. (Ich verstehe wirklich nicht, wie sich die Wahl von IM oder FMIF auf dieses Problem auswirkt. Bitte erläutern Sie dies.)
- Ich verstehe, dass FMIF "meinen Namespace verschmutzt", aber abgesehen davon, dass es sich um eine negativ klingende Phrase handelt, weiß ich nicht zu schätzen, wie sehr dies den Code auf konkrete Weise verletzt.
Danke vielmals.
python
python-import
unutbu
quelle
quelle
Antworten:
Die Negative, die Sie für IM / FPIM auflisten, können häufig durch geeignete Verwendung einer
as
Klausel verbessert werden .from some.package import mymodulewithalongname as mymod
kann Ihren Code sinnvoll verkürzen und seine Lesbarkeit verbessern. Wenn Sie ihnmymodulewithalongname
insomethingcompletelydifferent
morgen umbenennen , kann dieas
Klausel als einzelne Anweisung zum Bearbeiten verwendet werden.Betrachten Sie Ihren Pro-FMIF-Punkt 3 (nennen Sie ihn R für die Umleitung) und Ihren Pro-FPIM-Punkt 2 (nennen Sie ihn F für Flexibilität): R bedeutet, den Verlust der Integrität von Modulgrenzen zu erleichtern, während F ihn verstärkt. Mehrere Funktionen, Klassen und Variablen in einem Modul sollen häufig zusammenarbeiten: Sie sollten nicht unabhängig voneinander auf unterschiedliche Bedeutungen umgeschaltet werden. Betrachten Sie beispielsweise das Modul
random
und seine Funktionenseed
unduniform
: Wenn Sie den Import nur eines Moduls auf ein anderes Modul umstellen würden, würden Sie die normale Verbindung zwischen Aufrufen vonseed
und Ergebnissen von Aufrufen von unterbrechenuniform
. Wenn ein Modul gut gestaltet ist, mit Zusammenhalt und Integrität, ist die Erleichterung von R, die Grenzen des Moduls aufzubrechen, tatsächlich negativ - es macht es einfacher, etwas zu tun, das Ihnen besser gehtnicht tun.Umgekehrt ist , was ermöglicht , F koordinierte Schalt gekoppelter Funktionen, Klassen und Variablen (so allgemein von Entitäten , die gehören zusammen, durch Modularität). Um beispielsweise das Testen wiederholbar zu machen (FPIM Pro-Punkt 1), verspotten Sie beide
seed
undrandom
dasrandom
Modul. Wenn Ihr Code FPIM folgt, sind Sie fertig, die Koordination ist garantiert. Wenn Sie jedoch Code haben, der die Funktionen direkt importiert hat, müssen Sie jedes dieser Module suchen und das Verspotten immer und immer wieder wiederholen. Um Tests perfekt wiederholbar zu machen, ist normalerweise auch ein "koordiniertes Verspotten" von Datums- und Zeitfunktionen erforderlich. Wenn Sie siefrom datetime import datetime
in einigen Modulen verwenden, müssen Sie sie alle finden und verspotten (sowie alle, die dies tun)from time import time
usw.), um sicherzustellen, dass alle Zeiten empfangen werden, in denen die verschiedenen Teile des Systems fragen: "Wie spät ist es jetzt?" sind vollkommen konsistent (wenn Sie FPIM verwenden, verspotten Sie nur die beiden relevanten Module).Ich mag FPIM, weil es wirklich nicht viel Mehrwert gibt, wenn ein mehrfach qualifizierter Name anstelle eines einfach qualifizierten Namens verwendet wird (während der Unterschied zwischen Barennamen und qualifizierten Namen sehr groß ist - Sie erhalten mit einem qualifizierten Namen so viel mehr Kontrolle, sei es einzeln oder multiplizieren, als Sie jemals mit einem Barennamen können!).
Na ja, ich kann nicht den ganzen Arbeitstag darauf verwenden, auf jeden Ihrer Punkte zu antworten - Ihre Frage sollte wahrscheinlich ein halbes Dutzend Fragen sein ;-). Ich hoffe, dass dies zumindest "Warum ist F besser als R" und einige der Verspottungs- / Testprobleme anspricht - es läuft darauf hinaus , gut gestaltete Modularität (über F) zu erhalten und zu verbessern, anstatt sie zu untergraben (über R).
quelle
seed
ohne sich zu ändernuniform
. FMIF ermöglicht es dem Code, auf subtile Weise zu brechen, wenn Sie nicht vorsichtig sind! FPIM erfordert eine verwandte Funktion, um verwandt zu bleiben. Dies verhindert, dass der oben genannte Fehler jemals auftritt. Ah, ich verstehe endlich. Vielen Dank. Mann, ich muss viel Code umschreiben ... :)from question.FMIF import point_2 as F, point_3 as R
.Der klassische Text dazu stammt, wie so oft, von Fredrik Lundh, dem Effbot. Sein Rat: Verwenden Sie immer Import - außer wenn Sie nicht sollten.
Mit anderen Worten, sei vernünftig. Persönlich finde ich, dass alles, was mehrere Module tief ist, über importiert wird
from x.y.z import a
- das Hauptbeispiel sind Django-Modelle. Aber wie alles andere ist es eine Frage des Stils, und Sie sollten eine konsistente haben - insbesondere bei Modulen wiedatetime
, bei denen sowohl das Modul als auch die darin enthaltene Klasse dasselbe heißen. Müssen Sie schreibendatetime.datetime.now()
oder nurdatetime.now()
? (In meinem Code immer der erstere.)Die Punkte 1 und 2 in Ihrer Fragenliste scheinen dasselbe Problem zu sein. Aufgrund der dynamischen Natur von Python ist es ziemlich einfach, ein Element im Namespace eines Moduls zu ersetzen, unabhängig davon, welche der Methoden Sie verwenden. Die Schwierigkeit tritt auf, wenn sich eine Funktion in einem Modul auf eine andere bezieht, die Sie verspotten möchten. In diesem Fall bedeutet der Import des Moduls anstelle der Funktionen, dass Sie dies tun können
module.function_to_replace = myreplacementfunc
und alles transparent funktioniert - dies ist jedoch über FPIM genauso einfach wie über IM.Ich verstehe auch nicht, wie Punkt 3 irgendetwas mit irgendetwas zu tun hat. Ich denke, Ihr Punkt 4 basiert jedoch auf einem Missverständnis. Keine der von Ihnen angegebenen Methoden verschmutzt Ihren Namespace. Das bedeutet , dass
from module import *
Sie überhaupt keine Ahnung haben, was Sie importieren, und dass Funktionen in Ihrem Code angezeigt werden können, ohne dass dem Leser ein Hinweis gegeben wird, woher sie stammen. Das ist schrecklich und sollte unter allen Umständen vermieden werden.quelle
import datetime, now = datetime.datetime.now
damit ich es bequem tun kannprint(now(), 'reading file X')
...somefunc()
in Zeile 2345 stammt. ""from X import Y
nur für Pakete, so dassY
noch ein Modul ist.datetime.dametime.now()
oft genug benutzt, um es nervig zu finden oder eine Ausnahme zu rechtfertigen. Aber wenn man darüber nachdenkt, ist es schade, dass der "kanonische" Weg, die aktuelle Zeit zu erhalten, in PythonTolle Antworten hier (ich habe sie alle positiv bewertet), und hier sind meine Gedanken zu diesem Thema:
Adressieren Sie zunächst jede Ihrer Kugeln:
(Angeblich) Vorteile von FMIF:
Vielleicht, aber Modulnamen sind normalerweise kurz genug, so dass dies nicht relevant ist. Sicher, es ist
datetime
aber auchos
,re
,sys
etc. Und Python hat innerhalb freie Zeilenumbrüche{ [ (
. Und für verschachtelte Module gibt es immeras
sowohl IM als auch FPIMEntschieden widersprechen. Beim Lesen von Fremdcode (oder meines eigenen Codes nach einigen Monaten) ist es schwierig zu wissen, woher die einzelnen Funktionen stammen. Qualifizierte Namen ersparen mir das Hin- und Hergehen von Zeile 2345 zum Moduldeklarationsheader. Und es gibt Ihnen auch Kontext : "
chisquare
? Was ist das? Oh, es ist vonscypy
? Ok, dann ein paar mathematische Sachen" . Und noch einmal, Sie können immer abkürzenscipy.stats.stats as scypyst
.scypyst.chisquare(...)
ist kurz genug mit allen Vorteilen eines qualifizierten Namens.import os.path as osp
ist ein weiteres gutes Beispiel, wenn man bedenkt, dass es sehr häufig vorkommt, 3 oder mehr seiner Funktionen in einem einzigen Aufruf zu verketten: join (expanduser (), basename (splitext ())) usw.Wie oft möchten Sie eine einzelne Funktion, aber nicht das gesamte Modul neu definieren? Modulgrenzen und Funktionskoordination sollten erhalten bleiben, und Alex hat dies bereits ausführlich erklärt. Für die meisten (alle?) Real-World-Szenarien ist, wenn dies
alt_module.x
ein praktikabler Ersatz istmodule.x
, wahrscheinlichalt_module
selbst ein Rückgang der Alternative fürmodule
, sodass sowohl IM als auch FPIM wie FMIF Einzeiler sind, vorausgesetzt, Sie verwendenas
.Tatsächlich
as
ist es dasjenige, das die ersten beiden Probleme (und das dritte) mildert, nicht FPIM. Sie können IM auch dafür verwenden:import some.long.package.path.x as x
für das gleiche Ergebnis wie FPIM.Keiner der oben genannten ist wirklich ein Profi von FMIF. Und die Gründe, warum ich IM / FPIM bevorzuge, sind:
Der Einfachheit und Konsistenz halber importiere ich beim Importieren von IM oder FPIM immer ein Modul , kein Objekt aus einem Modul. Denken Sie daran, dass FMIF (ab-) zum Importieren von Funktionen, Klassen, Variablen oder sogar anderen Modulen verwendet werden kann! Denken Sie an das Durcheinander von
from somemodule import sys, somevar, os, SomeClass, datetime, someFunc
.Wenn Sie mehr als ein einzelnes Objekt von einem Modul möchten, verschmutzt FMIF Ihren Namespace stärker als IM oder FPIM, das einen einzelnen Namen verwendet, unabhängig davon, wie viele Objekte Sie verwenden möchten. Und solche Objekte haben einen qualifizierten Namen, der ein Vorteil und kein Nachteil ist: Wie ich in Ausgabe 2 gesagt habe, verbessert IMHO a die Lesbarkeit.
Alles hängt von Konsistenz, Einfachheit und Organisation ab. "Module importieren, keine Objekte" ist ein gutes, einfaches Denkmodell.
quelle
Wie Alex Martelli verwende ich gerne
as
beim Importieren einer Funktion.Eine Sache, die ich getan habe, ist, ein Präfix für alle Funktionen zu verwenden, die aus demselben Modul importiert wurden:
from random import seed as r_seed from random import random as r_random
r_seed
ist kürzer zu tippen alsrandom.seed
, behält aber die Modulgrenzen etwas bei. Jemand, der beiläufig auf Ihren Code schaut, kann sehenr_seed()
undr_random()
haben die Chance zu erkennen, dass sie verwandt sind.Natürlich können Sie immer einfach tun:
import random as r
und dann verwenden Sie
r.random()
undr.seed()
, was der ideale Kompromiss für diesen Fall sein kann. Ich verwende den Präfixtrick nur, wenn ich eine oder zwei Funktionen aus einem Modul importiere. Wenn ich viele Funktionen aus demselben Modul verwenden möchte, importiere ich das Modul, möglicherweise mit einemas
, um den Namen zu verkürzen.quelle
Ich stimme MestreLion hier am meisten zu (und damit eine Gegenstimme).
Meine Perspektive: Ich überprüfe häufig Code, mit dem ich nicht vertraut bin, und es ist ziemlich frustrierend, nicht zu wissen, aus welchem Modul eine Funktion stammt, wenn ich nur die Funktion betrachte.
Code wird einmal geschrieben und viele Male gelesen, sodass Lesbarkeit und Wartbarkeit die einfache Eingabe vereinfachen.
In ähnlicher Weise wird Code normalerweise nicht zum Nutzen des Codierers geschrieben, sondern zum Nutzen einer anderen Entität.
Ihr Code sollte für jemanden lesbar sein, der Python besser kennt als Sie, aber mit dem Code nicht vertraut ist.
Vollständige Pfadimporte können IDE auch dabei helfen, Sie auf die richtige Quelle der Funktion oder des Objekts zu verweisen, die Sie betrachten.
Aus all diesen und den von MestreLion festgestellten Gründen komme ich zu dem Schluss, dass es die beste Vorgehensweise ist, den vollständigen Pfad zu importieren und zu verwenden.
quelle