x = 3
y = [3]
def test1():
x += 1
print x
def test2():
y[0] = 4
y.append(5)
print y
test2()
test1()
这段代码执行结果: test2()成功打印[4, 5], test1()却报错: UnboundLocalError: local variable 'x' referenced before assignment
想不明白,为什么会这样,全局变量在函数里可以直接打印,但是如果要改变它的值,会报错,但是test2()为什么不报错?如果把y换成dict类型,就能在函数里不需要用global声明,可以直接改变y的值,但如果是str或number,就会报错,为什么?
En fait, cette question peut être mise de côté si l'objet référencé par la variable est mutable ou immuable. Ce à quoi nous devons prêter attention, c'est le positionnement de la variable, le moment et la portée de. la définition.
Considérez le code suivant :
Ce code générera une erreur :
a
est la variable param de la fonctiontest
, elle appartient donc à une variable locale, et sa portée est la fonctiontest
Nous passons 1 pour a auquel faire référence, donc il n'y a pas de gros problème. avecprint(a)
.Mais
b
n'est pas défini du début à la fin. Même si vous recherchez selon le principe LEGB, vous ne le trouvez pas, vous relancez donc unNameError
.Pour résoudre ce problème, peut-être pouvons-nous définir une variable globale :
Bien, cette fois il ne semble y avoir aucun problème, car Python a trouvé
b
dans le cadre de global La raison pour laquelle Python utilise globalb
est parce que nous n'avons pas définib
en local.Ensuite, nous commençons à attribuer des variables dans la fonction :
Résultat :
Les deux
print
dans la fonction ont imprimé 1 et 20 sans surprise, mais pourquoi la valeur deb
imprimée après avoir quitté la fonction était-elle de 100 ?Parce que nous avons écrit cela dans la fonction A l'affectation est également une définition
b = 20
, donc lestest
vus dansb
sont tous locaux, pas globaux, donc toutes les modifications que nous apportons àb
Aucune modification n'affectera leb
global. 🎜>.Cela nous dit :
Alors comment pouvons-nous opérer des variables globales au sein de la fonction ? Cela nécessite l'aide du mot-clé
global
:Avec le mot-clé
global
décrivantb
, Python traitera letest
dansb
comme une variable d'accès aub
global etb = 20
ne sera traité que comme une action d'affectation ne définit pas de nouvelle variable locale.Regardons un exemple plus déroutant :
Résultat :
apparaît ici
UnboundLocalError
, pourquoi cela se produit-il ? La raison est très simple,b
a une action d'affectation et de définition dans cette fonction :b = 20
, donc lestest
à l'intérieur deb
sont locaux (globaux n'est pas utilisé ici pour indiquer queb
est global), donc lorsqueprint(b)
est utilisé, Python essaiera de récupérer localb
au lieu de globalb
, mais la tragédie est qu'ici Dans la première étape, localb
n'a pas été attribué, on dit donc quelocal variable 'b' referenced before assignment
a été référencé avant d'être attribué, ce qui n'est naturellement pas possible.Regardez l'exemple que vous avez donné :
Ici, la définition de
test1
apparaît dansx
(il n'y a pas de global, etx
apparaît à gauche du signe égal. Naturellement, lorsque vous faites référence àx
, vous voudrez). utilisez local, mais parce que :Donc, lorsque vous souhaitez obtenir la valeur référencée par
x
à droite du signe égal, vous constatez qu'aucune valeur ne lui a encore été attribuée. Alors c'est la même chose que l'exemple ci-dessus :Quant à votre
test2
il n'y aura aucun problème :est parce que y n'apparaît pas à gauche du signe égal dans
!test2
, donc Python suppose automatiquement que globaly
est utilisé, donc naturellement il n'y a pas de problèmeConclusion
Pour voir si une variable locale est définie dans une fonction, vérifiez si le nom de la variable apparaît à gauche du signe égal et si le nom de la variable n'est pas spécifié par
global
Si une variable locale est définie, Python ne recherchera pas de variable globale, sinon Python utilisera automatiquement la variable globale
Si une variable locale est définie mais que vous lisez la référence avant que la variable ne soit attribuée, une UnboundLocalError apparaîtra
Pour résoudre ce problème, pensez à ajouter
global
pour indiquer l'intégralité du domaine, sinon cette méthode d'écriture ne devrait pas apparaître (opération sur place, ou affectation ultérieure)Des problèmes similaires se produiront également dans les fonctions locales. La solution est d'ajouter
nonlocal
(Python3), mais c'est une autre histoire.Questions auxquelles j'ai répondu : Python-QA
La portée des variables de Python est stipulée de cette manière. Dans test1, vous pouvez
print x
mais ne pouvez pas modifier xCertaines personnes disent que "les variables globales dans la portée locale doivent être en lecture seule", mais ce n'est pas vrai pour variables de référence. . .
Cet endroit en python est vraiment déroutant
En termes simples, la liaison des variables globales ne peut pas être modifiée dans la portée locale et l'adresse de la variable ne peut pas être modifiée dans
CPython
.Voir : Erreur courante 4 dans : Les dix erreurs les plus courantes commises par les programmeurs Python : mauvaise compréhension de l'analyse des noms de variables en Python
Votre fonction
Dans la fonctiontest1
a une opération d'affectationx += 1
, qui est considérée par l'interpréteur Python comme une variable dans la portée locale de la fonction. Cependant, la variablex
n'est pas définie avant l'affectation, etx
estnumber
, appartient au type immuable. Pour attribuer de nouvelles valeurs au type immuable, vous devez recréer un objet de type immuable et rediriger la variable d'origine vers l'objet nouvellement créé, mais cela l'objet nouvellement créé n'est pas inclus dansLEGB
Introuvable, donc une erreur sera signalée
Toutes les opérations d'affectation danstest2
,y
est unlist
, qui est un type de variable. La liste pointe toujours vers la même adresse mémoire après l'ajout, car la liste est un type de variable et peut être modifiée sur place. , cela ne signale pas d'erreurPython
sont essentiellement divisées en trois étapes suivantes (en prenanta = 3
comme exemple) :Créer un objet pour représenter la valeur
3
Créer une variable
a
, si elle n'a pas encore été crééeConnectez la variable
a
au nouvel objet3
Observons les changements d'adresse mémoire de la variable
test2
lors de l'exécution de votrey
fonctionSortie
Vous pouvez voir que
y
est en fait modifié sur place, il n'est donc pas nécessaire de créer des variables à plusieurs reprises ; et pour le type immuablex
, pour lui attribuer une valeur, vous devez d'abord créer un nouvel objet, même si le nom Identique, vous pouvez voir que si des affectations différentes sont effectuées à chaque fois, l'adresse mémoire dex
est en fait différente, ce qui peut aussi expliquer pourquoistr
ounumber
signaleront une erreur