J'ai essayé de trouver un guide complet pour savoir s'il est préférable d'utiliser import module
ou from module import
? Je viens de commencer avec Python et j'essaie de commencer avec les meilleures pratiques à l'esprit.
Fondamentalement, j'espérais que quelqu'un pourrait partager leurs expériences, quelles préférences les autres développeurs ont et quelle est la meilleure façon d'éviter tout problème ?
python
python-import
Filip Dupanović
la source
la source
from … import …
syntaxe en Python et 'module d'importation' contre 'à partir de la fonction d'importation de module''from module import X,Y,Z
et'from module import *
. Ce dernier pollue votre espace de noms et peut donner des résultats imprévisibles selon ce qui se passe dans le module. Pire encore faitfrom module import *
avec plusieurs modules.Réponses:
La différence entre
import module
etfrom module import foo
est principalement subjective. Choisissez celui que vous préférez et soyez cohérent dans votre utilisation. Voici quelques points pour vous aider à décider.import module
import
relevés. Vous n'avez pas besoin d'ajouter d'importations supplémentaires pour commencer à utiliser un autre élément du modulemodule.foo
votre code peut être fastidieux et redondant (l'ennui peut être minimisé en utilisantimport module as mo
puis en tapantmo.foo
)from module import foo
foo
import
relevéfoo
. Par exemple, il est moins clair de savoir ceceil()
quemath.ceil()
L'une ou l'autre méthode est acceptable, mais ne l' utilisez pas
from module import *
.Pour tout ensemble de code raisonnable et volumineux, si vous
import *
le cimenterez probablement dans le module, vous ne pourrez pas le supprimer. En effet, il est difficile de déterminer quels éléments utilisés dans le code proviennent du `` module '', ce qui permet d'arriver facilement au point où vous pensez que vous n'utilisezimport
plus, mais il est extrêmement difficile d'être sûr.la source
from module import *
peut être particulièrement utile, si vous l' utilisez comme:if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *
. Votre module parent peut alors potentiellement contenir des noms de fonction indépendants du système d'exploitation, si les noms de fonction dans module_lin et module_win ont les mêmes noms. C'est comme hériter conditionnellement de l'une ou l'autre classe.Il y a un autre détail ici, non mentionné, lié à l'écriture dans un module. Certes, cela n'est peut-être pas très courant, mais j'en ai besoin de temps en temps.
En raison de la façon dont les références et la liaison de noms fonctionnent en Python, si vous souhaitez mettre à jour un symbole dans un module, dites foo.bar, depuis l'extérieur de ce module, et que d'autres codes d'importation "voient" ce changement, vous devez importer foo a certaine manière. Par exemple:
module foo:
module a:
module b:
Cependant, si vous importez des noms de symboles au lieu de noms de modules, cela ne fonctionnera pas.
Par exemple, si je fais cela dans le module a:
Aucun code en dehors d'un ne verra la barre comme "oranges" parce que mon réglage de la barre a simplement affecté le nom "bar" à l'intérieur du module a, il n'a pas "atteint" l'objet du module foo et mis à jour sa "barre".
la source
Même si beaucoup de gens ont déjà expliqué à propos de
import
vsimport from
, je veux essayer d'expliquer un peu plus ce qui se passe sous le capot et où se trouvent tous les endroits où cela change.import foo
:Importe
foo
et crée une référence à ce module dans l'espace de noms actuel. Ensuite, vous devez définir le chemin d'accès au module terminé pour accéder à un attribut ou une méthode particulière depuis l'intérieur du module.Par exemple
foo.bar
mais pasbar
from foo import bar
:Importe
foo
et crée des références à tous les membres répertoriés (bar
). Ne définit pas la variablefoo
.Par exemple,
bar
mais pasbaz
oufoo.baz
from foo import *
:Importe
foo
et crée des références à tous les objets publics définis par ce module dans l'espace de noms actuel (tout ce qui est répertorié dans__all__
s'il__all__
existe, sinon tout ce qui ne commence pas_
). Ne définit pas la variablefoo
.Par exemple
bar
etbaz
mais pas_qux
oufoo._qux
.Voyons maintenant quand nous le faisons
import X.Y
:Vérifiez
sys.modules
avec nomos
etos.path
:Vérifier
globals()
etlocals()
dicter l'espace de noms avecos
etos.path
:À partir de l'exemple ci-dessus, nous avons constaté que seul
os
est inséré dans l'espace de noms local et global. Donc, nous devrions pouvoir utiliser:Mais non
path
.Une fois que vous avez supprimé l'
os
espace de noms de locals (), vous ne pourrez plus y accéderos
aussi bienos.path
qu'ils existent dans sys.modules:Parlons maintenant de
import from
:from
:Vérifiez
sys.modules
auprès deos
etos.path
:Nous avons constaté que
sys.modules
nous avons trouvé la même chose qu'avant en utilisantimport name
OK, vérifions à quoi ça ressemble dans
locals()
et lesglobals()
espaces de noms dict:Vous pouvez y accéder en utilisant un nom et
path
non enos.path
:Supprimons le «chemin» de
locals()
:Un dernier exemple utilisant un alias:
Et aucun chemin défini:
la source
as SYMBOL
change le fonctionnement de cette réponse?Les deux méthodes sont prises en charge pour une raison: il y a des moments où l'une est plus appropriée que l'autre.
import module
: agréable lorsque vous utilisez de nombreux bits du module. l'inconvénient est que vous devrez qualifier chaque référence avec le nom du module.from module import ...
: agréable que les éléments importés soient utilisables directement sans préfixe de nom de module. L'inconvénient est que vous devez répertorier chaque chose que vous utilisez et que le code ne précise pas d'où vient quelque chose.L'option à utiliser dépend de ce qui rend le code clair et lisible, et a plus que peu à voir avec les préférences personnelles. Je penche vers
import module
généralement parce que dans le code, il est très clair d'où vient un objet ou une fonction. J'utilisefrom module import ...
quand j'utilise beaucoup d' objet / fonction dans le code.la source
from M import X
les avantages des qualificatifs et d'en profiter quand même? Il semble que vous puissiez tirer le meilleur parti des deux mondes si vous pouviez encore le faireM.X
après cette importation.class m: from something.too.long import x, y, z
. Je ne le recommanderais pas vraiment.Personnellement, j'utilise toujours
puis accédez à tout comme
etc. La raison en est qu'en même temps, vous avez une invocation courte et que vous définissez clairement l'espace de noms des modules de chaque routine, ce qui est très utile si vous devez rechercher l'utilisation d'un module donné dans votre source.
Inutile de dire, n'utilisez pas l'importation *, car cela pollue votre espace de noms et ne vous dit pas d'où vient une fonction donnée (de quel module)
Bien sûr, vous pouvez rencontrer des problèmes si vous avez le même nom de module pour deux modules différents dans deux packages différents, comme
dans ce cas, bien sûr, vous rencontrez des problèmes, mais il y a alors un indice fort que votre disposition de package est défectueuse, et vous devez la repenser.
la source
Il est préférable d'utiliser de nombreuses fonctions du module.
Est préférable lorsque vous voulez éviter de polluer l'espace de noms global avec toutes les fonctions et types d'un module lorsque vous en avez seulement besoin
function
.la source
Je viens de découvrir une différence plus subtile entre ces deux méthodes.
Si le module
foo
utilise une importation suivante:Le module
bar
peut alors, par erreur, être utilisécount
comme s'il était défini dansfoo
, et non dansitertools
:Si
foo
utilise:l'erreur est toujours possible, mais moins susceptible d'être commise.
bar
a besoin de:Cela m'a causé des ennuis. J'ai eu un module qui par erreur a importé une exception à partir d'un module qui ne l'a pas définie, l'a seulement importée d'un autre module (en utilisant
from module import SomeException
). Lorsque l'importation n'était plus nécessaire et supprimée, le module incriminé était cassé.la source
Voici une autre différence non mentionnée. Ceci est copié textuellement de http://docs.python.org/2/tutorial/modules.html
Notez que lors de l'utilisation
l'élément peut être soit un sous-module (ou sous-package) du package, soit un autre nom défini dans le package, comme une fonction, une classe ou une variable. L'instruction import teste d'abord si l'élément est défini dans le package; sinon, il suppose qu'il s'agit d'un module et tente de le charger. S'il ne le trouve pas, une exception ImportError est déclenchée.
Au contraire, lors de l'utilisation d'une syntaxe comme
chaque article à l'exception du dernier doit être un emballage; le dernier élément peut être un module ou un package mais ne peut pas être une classe ou une fonction ou une variable définie dans l'élément précédent.
la source
Puisque je suis aussi un débutant, je vais essayer d'expliquer cela de manière simple: En Python, nous avons trois types de
import
déclarations qui sont:1. Importations génériques:
ce type d'importation est mon préféré, le seul inconvénient de cette technique d'importation est que si vous avez besoin d'utiliser la fonction d'un module, vous devez utiliser la syntaxe suivante:
bien sûr, cela augmente l'effort de frappe mais en tant que débutant, il vous aidera à garder une trace du module et de la fonction qui lui est associée (un bon éditeur de texte réduira considérablement l'effort de frappe et est recommandé).
L'effort de frappe peut être encore réduit en utilisant cette instruction d'importation:
maintenant, au lieu d'utiliser,
math.sqrt()
vous pouvez utiliserm.sqrt()
.2. Importation de fonctions:
ce type d'importation est mieux adapté si votre code n'a besoin d'accéder qu'à une ou plusieurs fonctions du module, mais pour utiliser tout nouvel élément du module, vous devez mettre à jour la déclaration d'importation.
3. Importations universelles:
Bien qu'il réduise considérablement l'effort de frappe, mais n'est pas recommandé car il remplira votre code avec diverses fonctions du module et leur nom pourrait entrer en conflit avec le nom des fonctions définies par l'utilisateur. exemple:
Si vous avez une fonction de votre propre sqrt nommé et que vous importez des mathématiques, votre fonction est sûre: il y a votre sqrt et il y a math.sqrt. Si vous faites de l'importation mathématique *, cependant, vous avez un problème: à savoir, deux fonctions différentes avec exactement le même nom. Source: Codecademy
la source
Avec
import
, le jeton doit être un module (un fichier contenant des commandes Python) ou un package (un dossier dans lesys.path
contenant un fichier__init__.py
.)Lorsqu'il y a des sous-packages:
les exigences pour le dossier (package) ou le fichier (module) sont les mêmes, mais le dossier ou le fichier doit être à l'intérieur
package2
qui doit être à l'intérieurpackage1
et les deuxpackage1
etpackage2
doivent contenir des__init__.py
fichiers.https://docs.python.org/2/tutorial/modules.htmlAvec le
from
style d'importation:le package ou le module entre dans l'espace de noms du fichier contenant l'
import
instruction au lieu demodule
(oupackage
)package1.package2.module
. Vous pouvez toujours vous lier à un nom plus pratique:Seul le
from
style d'importation vous permet de nommer une fonction ou une variable particulière:est autorisé, mais
n'est pas autorisé.
la source
Pour ajouter à ce que les gens ont dit
from x import *
: en plus de rendre plus difficile la provenance des noms, cela désactive les vérificateurs de code comme Pylint. Ils rapporteront ces noms en tant que variables non définies.la source
Ma propre réponse à cela dépend principalement du premier nombre de modules différents que j'utiliserai. Si je ne vais en utiliser qu'un ou deux, j'utiliserai souvent
from
...import
car cela fait moins de frappes dans le reste du fichier, mais si je vais utiliser de nombreux modules différents, je préfère justeimport
car cela signifie que chaque référence de module est auto-documentée. Je peux voir d'où vient chaque symbole sans avoir à chercher.Habituellement, je préfère le style d'auto-documentation de l'importation simple et ne passe à partir de .. import lorsque le nombre de fois où je dois taper le nom du module dépasse 10 à 20, même s'il n'y a qu'un seul module importé.
la source
L'une des différences importantes que j'ai découvert et dont personne n'a étonnamment parlé, c'est qu'en utilisant l' importation simple, vous pouvez accéder au module importé
private variable
et àprivate functions
partir de celui-ci, ce qui n'est pas possible avec l' instruction from-import .Code dans l'image:
setting.py
plain_importer.py
from_importer.py
la source
Importer un module - Vous n'avez pas besoin d'efforts supplémentaires pour extraire autre chose du module. Il présente des inconvénients tels que la frappe redondante
Module Import From - Moins de frappe et plus de contrôle sur les éléments d'un module accessibles. Pour utiliser un nouvel élément du module, vous devez mettre à jour votre déclaration d'importation.
la source
Il existe des modules intégrés qui contiennent principalement des fonctions nues ( base64 , mathématiques , os , shutil , sys , time , ...) et c'est certainement une bonne pratique que ces fonctions nues soient liées à un espace de noms et améliorent ainsi la lisibilité de votre code. Considérez combien il est plus difficile de comprendre la signification de ces fonctions sans leur espace de noms:
que lorsqu'ils sont liés à un module:
Parfois, vous avez même besoin de l'espace de noms pour éviter les conflits entre les différents modules ( json.load vs pickle.load )
D'autre part, certains modules contiennent principalement des classes ( configparser , datetime , tempfile , zipfile , ...) et beaucoup d'entre eux rendent leurs noms de classe suffisamment explicites:
il peut donc y avoir un débat quant à savoir si l'utilisation de ces classes avec l'espace de noms de module supplémentaire dans votre code ajoute de nouvelles informations ou allonge simplement le code.
la source
Je voudrais ajouter à cela, il y a des choses à considérer lors des appels d'importation:
J'ai la structure suivante:
main.py:
dis.dis montre la différence:
Au final, ils se ressemblent (STORE_NAME est le résultat dans chaque exemple), mais cela vaut la peine d'être noté si vous devez considérer les quatre importations circulaires suivantes:
Exemple 1
Cela marche
exemple2
Pas de dé
exemple3
Problème similaire ... mais clairement de x import y n'est pas le même que l'importation import xy comme y
exemple4
Celui-ci fonctionne également
la source
Voici ma structure de répertoires de mon répertoire actuel:
L'
import
instruction se souvient de tous les noms intermédiaires .Ces noms doivent être qualifiés:
L'
from ... import ...
instruction se souvient uniquement du nom importé .Ce nom ne doit pas être qualifié:
la source
Comme Jan Wrobel mentionne, l'un des aspects des différentes importations est la manière dont les importations sont divulguées.
Module mymath
Utilisation de mymath :
Si j'ai importé
gcd
uniquement pour un usage interne, ne pas le divulguer aux utilisateurs demymath
, cela peut être gênant. Je l'ai assez souvent, et dans la plupart des cas, je veux "garder mes modules propres".Outre la proposition de Jan Wrobel de masquer cela un peu plus en utilisant à la
import math
place, j'ai commencé à cacher les importations de la divulgation en utilisant un soulignement principal:Dans les grands projets, cette "meilleure pratique" me permet de contrôler exactement ce qui est divulgué aux importations ultérieures et ce qui ne l'est pas. Cela maintient mes modules propres et rapporte à une certaine taille de projet.
la source