web-dev-qa-db-fra.com

Python 3: UnboundLocalError: variable locale référencée avant l'affectation

Le code suivant donne l'erreur UnboundLocalError: local variable 'Var1' referenced before assignment:

Var1 = 1
Var2 = 0
def function(): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()

Comment puis-je réparer cela? Merci pour toute aide!

154
Eden Crow

Vous pouvez résoudre ce problème en passant des paramètres plutôt que de compter sur Globals

def function(Var1, Var2): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    return Var1 - 1
function(1, 1)
42
Jakob Bowyer

En effet, même si Var1 existe, vous utilisez également une instruction d'affectation sur le nom Var1 à l'intérieur de la fonction (Var1 -= 1 à la dernière ligne). Naturellement, cela crée une variable à l'intérieur de la portée de la fonction appelée Var1 (à vrai dire, un -= ou += met uniquement à jour (réaffecte) une variable existante, mais pour des raisons inconnues (cohérence probable). contexte), Python le traite comme une affectation). L’interprète Python voit cela au moment du chargement du module et décide (correctement) que la portée globale Var1 ne doit pas être utilisée dans la portée locale, ce qui pose un problème lorsque vous essayez de référencer le variable avant qu'il soit assigné localement.

L'utilisation de variables globales, en dehors de la nécessité, est généralement désapprouvée par les développeurs Python, car cela conduit à un code source de confusion et problématique. Cependant, si vous souhaitez les utiliser pour accomplir ce que votre code implique, vous pouvez simplement ajouter:

global Var1, Var2

dans le haut de votre fonction. Ceci indiquera à Python que vous n'avez pas l'intention de définir une variable Var1 ou Var2 à l'intérieur de la portée locale de la fonction. L’interprète Python voit cela au moment du chargement du module et décide (correctement) de rechercher toutes les références aux variables susmentionnées dans la portée globale.

Quelques ressources

  • le site Web Python dispose d'un excellente explication pour ce problème courant.
  • Python 3 propose une instruction nonlocal connexe - vérifiez-la également.
364
orokusaki

Si vous définissez la valeur d'une variable dans la fonction, python la comprend comme la création d'une variable locale portant ce nom. Cette variable locale masque la variable globale.

Dans votre cas, Var1 est considéré comme une variable locale, et il est utilisé avant d'être défini, d'où l'erreur.

Pour résoudre ce problème, vous pouvez explicitement dire que c'est un global en mettant global Var1 dans votre fonction.

Var1 = 1
Var2 = 0
def function():
    global Var1
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()
72
madjar

Je n'aime pas ce comportement, mais c'est comme ça que Python fonctionne. D'autres ont déjà répondu à la question, mais pour être complet, permettez-moi de souligner que Python 2 a plus de telles bizarreries.

def f(x):
    return x

def main():
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

Python 2.7.6 renvoie une erreur:

Traceback (most recent call last):
  File "weird.py", line 9, in <module>
    main()
  File "weird.py", line 5, in main
    print f(3)
UnboundLocalError: local variable 'f' referenced before assignment

Python voit que la variable f est utilisée comme variable locale dans [f for f in [1, 2, 3]] et décide qu'il s'agit également d'une variable locale dans f(3). Vous pouvez ajouter une instruction global f:

def f(x):
    return x

def main():
    global f
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

Ça marche; cependant, f devient 3 à la fin ... C’est-à-dire que print [f for f in [1, 2, 3]] change maintenant la variable globale f en 3, ce n’est donc pas une fonction quelconque. plus.

Heureusement, cela fonctionne très bien en Python3 après l’ajout des parenthèses à print.

9
osa

Pourquoi ne pas simplement renvoyer votre valeur calculée et laisser l’appelant modifier la variable globale. Ce n'est pas une bonne idée de manipuler une variable globale dans une fonction, comme ci-dessous:

Var1 = 1
Var2 = 0

def function(): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    return Var1 - 1

Var1 = function()

ou même faire des copies locales des variables globales et travailler avec elles et renvoyer les résultats que l'appelant peut ensuite assigner de manière appropriée

def function():
v1, v2 = Var1, Var2
# calculate using the local variables v1 & v2
return v1 - 1

Var1 = function()
2
ctx