UnboundLocalError en Python [dupliquer]
cette question a déjà une réponse ici:
- comment changer une variable après Qu'elle soit déjà définie en Python 6 réponses
- Utilisation de variables globales dans une fonction 18 réponses
Qu'est-ce que je fais de mal ici?
counter = 0
def increment():
counter += 1
increment()
le code ci-dessus lance un UnboundLocalError
.
8 réponses
Python n'a pas de déclarations de variables, il doit donc comprendre le scope de variables lui-même. Il le fait par une règle simple: S'il y a une affectation à une variable à l'intérieur d'une fonction, cette variable est considérée comme locale. [1] ainsi ,la ligne
counter += 1
rend implicitement counter
local à increment()
. Essayez d'exécuter cette ligne, cependant, essayez de lire le valeur de la variable locale counter
avant son attribution, résultant en un UnboundLocalError
. [2]
si counter
est une variable globale, le mot-clé global
aidera. Si increment()
est une fonction locale et counter
une variable locale, vous pouvez utiliser nonlocal
en Python 3.x.
vous devez utiliser le global statement de sorte que vous modifiez le compteur de variables global, au lieu d'une variable locale:
counter = 0
def increment():
global counter
counter += 1
increment()
si le champ d'application qui contient la définition de counter
n'est pas le champ d'application global, on Python 3.x vous pouvez utiliser le déclaration non locale . Dans la même situation sur Python 2.x vous n'auriez aucun moyen de réattribuer au nom non local counter
, donc vous auriez besoin de faire counter
mutable et le modifier:
counter = [0]
def increment():
counter[0] += 1
increment()
print counter[0] # prints '1'
pour répondre à la question dans votre ligne d'objet,* oui, il y a des fermetures en Python, sauf qu'elles ne s'appliquent qu'à l'intérieur d'une fonction, et aussi (en Python 2.x) ils sont en lecture seule; vous ne pouvez pas re-lier le nom à un objet différent (bien que si l'objet est mutable, vous pouvez modifier son contenu). En Python 3.x, vous pouvez utiliser le mot-clé nonlocal
pour modifier une variable de fermeture.
def incrementer():
counter = 0
def increment():
nonlocal counter
counter += 1
return counter
return increment
increment = incrementer()
increment() # 1
increment() # 2
* le titre original de la question portait sur les fermetures en Python.
la raison pour laquelle votre code lance un UnboundLocalError
est déjà bien expliquée dans d'autres réponses.
mais il me semble que vous essayez de construire quelque chose qui fonctionne comme itertools.count()
.
Alors pourquoi ne pas l'essayer, et voir si elle convient à votre cas:
>>> from itertools import count
>>> counter = count(0)
>>> counter
count(0)
>>> next(counter)
0
>>> counter
count(1)
>>> next(counter)
1
>>> counter
count(2)
Pour modifier une variable globale dans une fonction, vous devez utiliser le mot clé global.
quand vous essayez de faire cela sans la ligne
global counter
à l'intérieur de la définition d'incrément, une variable locale nommée counter est créée afin de vous empêcher de salir la variable counter sur laquelle tout le programme peut dépendre.
notez que vous n'avez besoin d'utiliser global que lorsque vous modifiez la variable; vous pouvez lire contrer de l'intérieur increment sans la nécessité de la déclaration globale.
Python a une portée lexicale par défaut, ce qui signifie que bien qu'une portée fermée puisse accéder à des valeurs dans sa portée qui l'entoure, elle ne peut pas les modifier (à moins qu'elles ne soient déclarées globales avec le mot-clé global
).
un dispositif de fermeture lie les valeurs de à l'environnement aux noms de local . L'environnement local peut alors utiliser la valeur liée, et même réaffecter que nom à quelque chose d'autre, mais il ne peut pas modifier la liaison dans l'environnement d'enclos.
Dans votre cas, vous essayez de traiter counter
comme une variable locale, plutôt que d'une valeur limite. Notez que ce code, qui lie la valeur de x
assignée dans l'environnement environnant, fonctionne très bien:
>>> x = 1
>>> def f():
>>> return x
>>> f()
1
essayez cette
counter = 0
def increment():
global counter
counter += 1
increment()
Python n'est pas purement lexicalement scopé.
voir: utiliser des variables globales dans une fonction autre que celle qui les a créées
et ceci: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes /