web-dev-qa-db-fra.com

Comment fonctionne Python importation exactement?

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?

49
corazza

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:

60
ThiefMaster

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 .

3
Casey Kuball