2010-05-13 15 views
156

Je suis nouveau sur Python, donc c'est probablement une simple question de portée. Le code suivant dans un fichier Python (module) me un peu déroutant:Quelle est la portée d'une variable initialisée dans une instruction if?

if __name__ == '__main__': 
    x = 1 

print x 

Dans d'autres langues que j'ai travaillé, ce code jetterait une exception, car la variable x est locale à la déclaration if et devrait n'existe pas en dehors de cela. Mais ce code s'exécute, et imprime 1. Quelqu'un peut-il expliquer ce comportement? Toutes les variables créées dans un module sont-elles globales/disponibles pour l'ensemble du module?

+7

Une autre anomalie que vous ignorez peut-être: si l'instruction 'if' ci-dessus n'est pas vraie (ie, __name__' est * not *' '__main __' ', par exemple lorsque vous importez le module au lieu de l'exécuter top-level), alors 'x' n'aura jamais été lié, et l'instruction' print x' qui suivra lancera un 'NameError: name 'x' n'est pas défini'. – Santa

Répondre

155

Les variables Python portent sur la fonction, la classe ou le module le plus interne dans lequel elles sont affectées. Les blocs de contrôle tels que if et while ne comptent pas. Par conséquent, une variable affectée à l'intérieur d'un if est toujours définie sur une fonction, une classe ou un module.

(fonctions implicites définies par une expression de générateur ou d'une liste/compréhension set/dict font nombre, comme les expressions lambda. Vous ne pouvez pas farcir une instruction d'affectation dans l'un de ceux, mais les paramètres lambda et for cibles clause sont implicitement.)

36

Oui, ils sont dans la même « portée locale », et le code fait comme celui-ci est commun en Python:

if condition: 
    x = 'something' 
else: 
    x = 'something else' 

use(x) 

Notez que x n'est pas déclarée ou initialisés avant que la condition, comme il le ferait être en C ou Java, par exemple. En d'autres termes, Python n'a pas d'étendues au niveau du bloc. Attention, cependant, avec des exemples tels que

if False: 
    x = 3 
print(x) 

qui soulèveraient clairement une exception NameError.

1

Oui. C'est également vrai pour la portée for. Mais pas de fonctions bien sûr.

Dans votre exemple: si la condition dans l'instruction if est false, x ne sera pas définie.

1

Vous exécutez ce code à partir de la ligne de commande; par conséquent, if conditions est true et x est défini. Comparer:

>>> if False: 
    y = 42 


>>> y 
Traceback (most recent call last): 
    File "<pyshell#6>", line 1, in <module> 
    y 
NameError: name 'y' is not defined 
28

Portée en python suit cet ordre:

  • Rechercher la portée locale

  • Rechercher la portée de toutes les encaissantes fonctions

  • Rechercher la portée globale

  • Rechercher dans les built-ins

(source)

Notez que if et d'autres constructions en boucle/branchement ne sont pas cotées - seules les classes, fonctions et modules fournissent la portée en Python, si quoi que ce soit déclaré dans un bloc if a la même portée comme quoi tout a disparu en dehors du bloc. Les variables ne sont pas vérifiées lors de la compilation, ce qui explique pourquoi les autres langues lèvent une exception. En python, tant que la variable existe au moment où vous en avez besoin, aucune exception ne sera levée.

5

Comme l'a dit Eli, Python ne nécessite pas de déclaration de variable.En C, vous diriez:

int x; 
if(something) 
    x = 1; 
else 
    x = 2; 

mais dans la déclaration Python est implicite, donc quand vous attribuez à x il est automatiquement déclaré. C'est parce que Python est dynamiquement typé - cela ne fonctionnerait pas dans un langage statique, car selon le chemin utilisé, une variable pourrait être utilisée sans être déclarée. Ce serait capturé à la compilation dans un langage typé statiquement, mais avec un langage typé dynamiquement c'est autorisé. La seule raison pour laquelle un langage de type statique est limité à devoir déclarer des variables en dehors de if instructions en raison de ce problème. Embrassez la dynamique!

7

Contrairement aux langages tels que C, une variable Python est dans la portée de l'ensemble de la fonction (ou classe, ou module) où elle apparaît, pas seulement dans le "bloc" le plus à l'intérieur. C'est comme si vous aviez déclaré int x en haut de la fonction (ou de la classe, ou du module), sauf qu'en Python vous n'avez pas besoin de déclarer les variables.

Notez que l'existence de la variable x est vérifiée uniquement au moment de l'exécution, c'est-à-dire lorsque vous obtenez l'instruction print x. Si __name__ n'était pas égal à "__main__", vous obtiendrez une exception: NameError: name 'x' is not defined.

+0

Les classes ne créent pas de portée; une variable "locale" dans une classe est simplement ajoutée à la dict de la classe lors de la création. – chepner