Comment fonctionne exactement l'importation de Python?
J'ai deux situations spécifiques où je ne comprends pas comment l'importation fonctionne en Python:
1ère situation spécifique:
Lorsque j'importe le même module dans deux scripts Python différents, le module n'est pas importé deux fois, n'est-ce pas? La première fois que Python le rencontre, il est importé, et la deuxième fois, vérifie-t-il si le module a été importé, ou fait-il une copie?
2ème situation spécifique:
Considérons le module suivant, appelé bla.py
:
a = 10
Et puis, nous avons foo.py
, un module qui importe bla.py
:
from bla import *
def Stuff ():
return a
Et après cela, nous avons un script appelé bar.py
, qui est exécuté par l'utilisateur:
from foo import *
Stuff() #This should return 10
a = 5
Stuff()
Ici, Je ne sais pas: Stuff()
renvoie-t-il 10 ou 5?
2 réponses
Partie 1
Le module n'est chargé qu'une seule fois, il n'y a donc pas de perte de performance en l'important à nouveau. Si vous vouliez réellement qu'il soit chargé/analysé à nouveau, vous devrez reload()
le module.
La première place cochée est
sys.modules
, le cache de tous les modules qui ont été importés précédemment. [source]
Partie 2
from foo import *
importe a
dans la portée locale. Lors de l'attribution d'une valeur à a
, elle est remplacée par la nouvelle valeur - mais la variable foo.a
d'origine n'est pas touchée.
Donc, sauf si vous import foo
et modifiez foo.a
, les deux appels retourneront la même valeur.
Pour un type mutable tel qu'une liste ou un dict, il serait différent, le modifier affecterait en effet la variable d'origine - mais lui attribuer une nouvelle valeur ne modifierait toujours pas foo.whatever
.
Si vous voulez des informations plus détaillées, jetez un oeil à http://docs.python.org/reference/executionmodel.html:
Les constructions suivantes lient les noms: les paramètres formels aux fonctions, les instructions d'importation , les définitions de classe et de fonction (celles-ci lient le nom de classe ou de fonction dans le bloc de définition) et les cibles qui sont des identificateurs si elles se produisent dans une affectation, pour l'en-tête de boucle,
Les deux gras les sections sont les plus pertinentes pour vous: d'Abord le nom de a
est lié à la valeur de foo.a
lors de l'importation. Ensuite, en faisant a = 5
, le nom a
est lié à 5
. Puisque la modification d'une liste / dict ne provoque aucune liaison, ces opérations modifieraient celle d'origine (b
et foo.b
sont liés au même objet sur lequel vous opérez). Assigner un nouvel objet à {[14] } serait à nouveau une opération de liaison et séparerait donc b
de foo.b
.
Il est également intéressant de noter ce que exactement l'instruction import
fait:
-
import foo
lie le nom du module à l'objet module dans la portée actuelle, donc si vous modifiezfoo.whatever
, Vous travaillerez avec le nom dans ce module - toutes les modifications / affectations affecteront la variable dans le module. -
from foo import bar
lie uniquement le(s) nom (S) donné (s) (c'est-à-direfoo
restera non lié) à l'élément portant le même nom dansfoo
- donc les opérations surbar
se comportent comme expliqué précédemment. -
from foo import *
se comporte comme le précédent un, mais il importe tous les noms globaux qui ne sont pas préfixés par un trait de soulignement. Si le module définit__all__
, seuls les noms à l'intérieur de cette séquence sont importés.
Partie 3 (qui n'existe même pas dans votre question :p)
La documentation python est extrêmement bonne et généralement verbeuse-vous trouvez une réponse sur presque toutes les questions possibles liées au langage. Voici quelques liens:
- http://docs.python.org/reference/datamodel.html (classes, propriétés, méthodes magiques, etc.) ()
- http://docs.python.org/reference/executionmodel.html (Comment fonctionnent les variables en python)
- http://docs.python.org/reference/expressions.html
-
http://docs.python.org/reference/simple_stmts.html (déclarations telles que
import
,yield
) -
http://docs.python.org/reference/compound_stmts.html (bloc de déclarations telles que
for
,try
,with
)
, pour répondre À votre première question:
Non, python n'est pas' importé ' deux fois. Lorsque python charge un module, il vérifie le module dans sys.modules
. Si elle n'est pas là, il est là, et chargé.
Pour répondre À votre deuxième question:
Les ModulesPeuvent définir les noms qu'ils exporteront dans un scénario from camelot import *
, et le comportement consiste à créer des noms pour les valeurs existantes, pas pour référencer des variables existantes (python n'a pas de références).
Sur un sujet quelque peu lié, faire un from camelot import *
est pas la même chose qu'une importation régulière .