Utilisez 'import module' ou 'from module import'?

411

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 ?

Filip Dupanović
la source
5
Je voulais juste vous faire savoir que la réponse choisie est fausse. Il indique que la différence est subjective alors qu'il y a une différence. Cela pourrait entraîner des bogues difficiles à détecter. Voir la réponse de Michael Ray Lovetts.
Mayou36
2
Il y a une énorme différence entre l'importation d'identifiants nommés spécifiques 'from module import X,Y,Zet'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 fait from module import *avec plusieurs modules.
smci

Réponses:

474

La différence entre import moduleet from module import fooest 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

  • Avantages:
    • Moins d'entretien de vos importrelevés. Vous n'avez pas besoin d'ajouter d'importations supplémentaires pour commencer à utiliser un autre élément du module
  • Les inconvénients:
    • Taper module.foovotre code peut être fastidieux et redondant (l'ennui peut être minimisé en utilisant import module as mopuis en tapant mo.foo)

from module import foo

  • Avantages:
    • Moins de frappe à utiliser foo
    • Plus de contrôle sur les éléments d'un module accessibles
  • Les inconvénients:
    • Pour utiliser un nouvel élément du module, vous devez mettre à jour votre importrelevé
    • Vous perdez du contexte foo. Par exemple, il est moins clair de savoir ce ceil()quemath.ceil()

L'une ou l'autre méthode est acceptable, mais ne l' utilisez pasfrom 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'utilisez importplus, mais il est extrêmement difficile d'être sûr.

Mark Roddy
la source
66
+1 pour décourager l'utilisation de "from module import *", il encombre juste l'espace de noms.
Christian Witts le
22
l'encombrement de l'espace de noms n'est pas la partie la plus problématique de l '"import *", c'est la réduction de la lisibilité: tout conflit de nom apparaîtra dans les tests (unitaires). Mais tous les noms que vous utilisez à partir du module importé seront nus, avec un indice quelconque d'où ils viennent. Je déteste absolument "importer *".
Jürgen A. Erhard
21
Le Zen de Python ne dit-il pas qu'explicite vaut mieux qu'implicite?
Antony Koch
8
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.
anishsane
19
@anishsane. Il y a une autre façon de procéder. importez module_win comme quelque chose. Ensuite, utilisez toujours quelque chose.method_name ()
Vinay
163

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:

bar = "apples"

module a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

module b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

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:

from foo import bar
bar = "oranges"

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".

Michael Ray Lovett
la source
Avec ce dernier exemple, pouvez-vous toujours appeler 'foo.bar = "orange"' pour mettre à jour 'bar' dans 'foo'?
velocirabbit
4
Non, dans le dernier exemple, le nom 'foo' est inconnu
Ghislain Leveque
31
CETTE réponse fournit la "vraie" réponse à la question: quelle est la différence entre les deux variantes d'importation
Mayou36
3
A écrit un extrait pour prouver que cette réponse est tout à fait juste, mais quelle est la raison derrière cela?
huangbeidu
Je pense que ce que vous dites est d'importer des noms de symboles pour avoir des variables locales mais d'importer des noms de modules pour avoir des variables globales ???
WinEunuuchs2Unix
79

Même si beaucoup de gens ont déjà expliqué à propos de importvs import 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 fooet 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.barmais pasbar

from foo import bar:

Importe fooet crée des références à tous les membres répertoriés ( bar). Ne définit pas la variable foo.

Par exemple, barmais pas bazoufoo.baz

from foo import *:

Importe fooet 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 baret bazmais pas _quxou foo._qux.


Voyons maintenant quand nous le faisons import X.Y:

>>> import sys
>>> import os.path

Vérifiez sys.modulesavec nom oset os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Vérifier globals()et locals()dicter l'espace de noms avec oset os.path:

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

À partir de l'exemple ci-dessus, nous avons constaté que seul osest inséré dans l'espace de noms local et global. Donc, nous devrions pouvoir utiliser:

 >>> os
 <module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

Mais non path.

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Une fois que vous avez supprimé l' osespace de noms de locals (), vous ne pourrez plus y accéder osaussi bien os.pathqu'ils existent dans sys.modules:

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Parlons maintenant de import from:

from:

>>> import sys
>>> from os import path

Vérifiez sys.modulesauprès de oset os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Nous avons constaté que sys.modulesnous avons trouvé la même chose qu'avant en utilisantimport name

OK, vérifions à quoi ça ressemble dans locals()et les globals()espaces de noms dict:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

Vous pouvez y accéder en utilisant un nom et pathnon en os.path:

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Supprimons le «chemin» de locals():

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Un dernier exemple utilisant un alias:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

Et aucun chemin défini:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
James Sapam
la source
8
Bien que ce soit verbeux, c'est vraiment la meilleure réponse dans la liste pour une question assez complexe. Il fournit un code réel pour aider à expliquer les subtilités «sous le capot», qui sont plus importantes que le style, pour ce problème particulier. J'aimerais pouvoir voter plus d'une fois!
Mike Williamson
Est-ce que l'utilisation as SYMBOLchange le fonctionnement de cette réponse?
Maximilian Burszley
40

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 modulegénéralement parce que dans le code, il est très clair d'où vient un objet ou une fonction. J'utilise from module import ...quand j'utilise beaucoup d' objet / fonction dans le code.

dwc
la source
1
Existe-t-il un moyen d'utiliser from M import Xles 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 faire M.Xaprès cette importation.
arthropode
@artgropod: Un peu. Tu peux le faire class m: from something.too.long import x, y, z. Je ne le recommanderais pas vraiment.
Lie Ryan
35

Personnellement, j'utilise toujours

from package.subpackage.subsubpackage import module

puis accédez à tout comme

module.function
module.modulevar

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

from package1.subpackage import module
from package2.subpackage import module

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.

Stefano Borini
la source
10
Dans le dernier cas, vous pouvez toujours utiliser: import pkgN.sub.module as modN vous donnant des noms distincts pour chaque module. Vous pouvez également utiliser le modèle 'import modulename as mod1' pour raccourcir un nom long, ou pour basculer entre les implémentations de la même API (par exemple les modules API DB) avec un seul changement de nom.
Jeff Shannon
15
import module

Il est préférable d'utiliser de nombreuses fonctions du module.

from module import function

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.

Andrew Hare
la source
7
Sûrement la seule chose dans l'espace de noms global si vous faites «module d'importation» est «module»? Vous ne polluez l'espace de noms que si vous effectuez "from .. import *".
John Fouhy
10

Je viens de découvrir une différence plus subtile entre ces deux méthodes.

Si le module fooutilise une importation suivante:

from itertools import count

Le module barpeut alors, par erreur, être utilisé countcomme s'il était défini dans foo, et non dans itertools:

import foo
foo.count()

Si fooutilise:

import itertools

l'erreur est toujours possible, mais moins susceptible d'être commise. bara besoin de:

import foo
foo.itertools.count()

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é.

Jan Wrobel
la source
10

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

from package import item

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

import item.subitem.subsubitem

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.

user2141737
la source
Une autre chose que j'ai remarquée est que si l'élément est également un sous-module dans le package, alors "à partir de l'élément d'importation de package" fonctionne mais "importation de package" package.item.subitem = ... ne fonctionne pas avec un init .py de package vide , sauf si nous avoir "importation d'élément" dans le fichier init du paquet.
Amitoz Dandiana
6

Puisque je suis aussi un débutant, je vais essayer d'expliquer cela de manière simple: En Python, nous avons trois types de importdéclarations qui sont:

1. Importations génériques:

import math

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:

math.sqrt(4)

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:

import math as m

maintenant, au lieu d'utiliser, math.sqrt()vous pouvez utiliser m.sqrt().

2. Importation de fonctions:

from math import sqrt

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:

from math import * 

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

Shashank Rawat
la source
5
import package
import module

Avec import, le jeton doit être un module (un fichier contenant des commandes Python) ou un package (un dossier dans le sys.pathcontenant un fichier __init__.py.)

Lorsqu'il y a des sous-packages:

import package1.package2.package
import package1.package2.module

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 package2qui doit être à l'intérieur package1et les deux package1et package2doivent contenir des __init__.pyfichiers.https://docs.python.org/2/tutorial/modules.html

Avec le fromstyle d'importation:

from package1.package2 import package
from package1.package2 import module

le package ou le module entre dans l'espace de noms du fichier contenant l' importinstruction au lieu de module(ou package) package1.package2.module. Vous pouvez toujours vous lier à un nom plus pratique:

a = big_package_name.subpackage.even_longer_subpackage_name.function

Seul le fromstyle d'importation vous permet de nommer une fonction ou une variable particulière:

from package3.module import some_function

est autorisé, mais

import package3.module.some_function 

n'est pas autorisé.

Bennett Brown
la source
4

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.

DNS
la source
3

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... importcar 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é.

SingleNegationElimination
la source
1

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 variableet à private functionspartir de celui-ci, ce qui n'est pas possible avec l' instruction from-import .

entrez la description de l'image ici

Code dans l'image:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work
Saurav Sahu
la source
0

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.

Dlucidone
la source
0

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:

copysign(foo, bar)
monotonic()
copystat(foo, bar)

que lorsqu'ils sont liés à un module:

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

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:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

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.

Jeyekomon
la source
0

Je voudrais ajouter à cela, il y a des choses à considérer lors des appels d'importation:

J'ai la structure suivante:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.dis montre la différence:

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

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

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

Cela marche

exemple2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

Pas de dé

exemple3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

Problème similaire ... mais clairement de x import y n'est pas le même que l'importation import xy comme y

exemple4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

Celui-ci fonctionne également

ahfx
la source
0

Voici ma structure de répertoires de mon répertoire actuel:

.  
└─a  
   └─b  
     └─c
  1. L' importinstruction se souvient de tous les noms intermédiaires .
    Ces noms doivent être qualifiés:

    In[1]: import a.b.c
    
    In[2]: a
    Out[2]: <module 'a' (namespace)>
    
    In[3]: a.b
    Out[3]: <module 'a.b' (namespace)>
    
    In[4]: a.b.c
    Out[4]: <module 'a.b.c' (namespace)>
  2. L' from ... import ...instruction se souvient uniquement du nom importé .
    Ce nom ne doit pas être qualifié:

    In[1]: from a.b import c
    
    In[2]: a
    NameError: name 'a' is not defined
    
    In[2]: a.b
    NameError: name 'a' is not defined
    
    In[3]: a.b.c
    NameError: name 'a' is not defined
    
    In[4]: c
    Out[4]: <module 'a.b.c' (namespace)>

  • Remarque: Bien sûr, j'ai redémarré ma console Python entre les étapes 1 et 2.
MarianD
la source
0

Comme Jan Wrobel mentionne, l'un des aspects des différentes importations est la manière dont les importations sont divulguées.

Module mymath

from math import gcd
...

Utilisation de mymath :

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

Si j'ai importé gcduniquement 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 mathplace, j'ai commencé à cacher les importations de la divulgation en utilisant un soulignement principal:

# for instance...
from math import gcd as _gcd
# or...
import math as _math

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.

matheburg
la source