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?

43
demandé sur corazza 2012-05-08 19:31:02

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 modifiez foo.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-à-dire foo restera non lié) à l'élément portant le même nom dans foo - donc les opérations sur bar 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:

53
répondu ThiefMaster 2012-05-08 15:57:34

, 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 Modules

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

2
répondu Darthfett 2012-05-08 15:54:43