J'ai deux situations spécifiques où je ne comprends pas comment fonctionne l'importation en Python:
1ère situation spécifique:
Lorsque j'importe le même module dans deux scripts Python, le module n'est pas importé deux fois, non? La première fois Python le rencontre, il est importé) , et la deuxième fois, vérifie-t-il si le module a été importé ou en fait-il une copie?
2ème situation spécifique:
Considérez 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?
Partie 1
Le module n'est chargé qu'une seule fois, il n'y a donc aucune perte de performances en l'important à nouveau. Si vous vouliez réellement qu'il soit à nouveau chargé/analysé, vous devriez 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 l'original foo.a
la variable n'est pas touchée.
Donc, sauf si vous import foo
et modifier foo.a
, les deux appels renverront la même valeur.
Pour un type mutable tel qu'une liste ou un dict, ce serait différent, le modifier affecterait en effet la variable d'origine - mais lui affecter une nouvelle valeur ne modifierait toujours pas foo.whatever
.
Si vous souhaitez des informations plus détaillées, consultez http://docs.python.org/reference/executionmodel.html :
Les constructions suivantes lient les noms: paramètres formels aux fonctions, instructions d'importation , définitions de classe et de fonction (celles-ci lient le nom de classe ou de fonction dans le bloc de définition), et des cibles qui sont des identifiants si elles se produisent dans une affectation , pour l'en-tête de boucle, dans la deuxième position d'un en-tête de clause except ou après comme dans une instruction with.
Les deux sections en gras sont celles qui vous conviennent: d'abord, le nom a
est lié à la valeur de foo.a
lors de l'importation. Ensuite, lorsque vous faites a = 5
, le nom a
est lié à 5
. Étant donné que 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). L'affectation d'un nouvel objet à b
serait à nouveau une opération de liaison et séparerait donc b
de foo.b
.
Il convient également de noter ce que fait exactement l'instruction import
:
import foo
lie le nom du module à l'objet module dans la portée actuelle, donc si vous modifiez foo.whatever
, vous travaillerez avec le nom dans ce module - toute modification/affectation affectera la variable dans le module.from foo import bar
lie le (s) nom (s) donné (s) (ie foo
restera non lié) à l'élément portant le même nom dans foo
- donc les opérations sur bar
se comportent comme expliqué plus haut .from foo import *
se comporte comme le précédent, 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 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 détaillée - vous y trouverez des réponses à presque toutes les questions liées à la langue. Voici quelques liens utiles:
import
, yield
)for
, try
, with
)Pour répondre à votre première question:
Non, python n'est pas "importé" deux fois. Lorsque python charge un module, il recherche le module dans sys.modules
. S'il n'est pas là, il est mis dedans et chargé.
Pour répondre à votre deuxième question:
Les modules peuvent définir les noms à exporter vers un from camelot import *
scénario, et le comportement consiste à créer des noms pour les valeurs existantes, pas à référencer des variables existantes (python n'a pas de références).
Sur un sujet quelque peu connexe, faire un from camelot import *
est différent de l'importation régulière .