web-dev-qa-db-fra.com

Comment changer une variable après qu'elle soit déjà définie?

J'essaie d'ajouter ou de soustraire une variable définie, mais je ne vois pas comment écraser l'ancienne valeur avec la nouvelle.

a = 15

def test():
    a = a +10
    print ( a )

test()

Message d'erreur:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 4, in test
    a = a +10
UnboundLocalError: local variable 'a' referenced before assignment
18
user7351337

L'erreur que vous obtenez lorsque vous essayez d'exécuter votre code est la suivante:

UnboundLocalError: local variable 'a' referenced before assignment

… Ce qui, à première vue, semble étrange: après tout, la déclaration first du code ci-dessus (a = 15) est une cession. Alors que se passe-t-il?

En fait, il se passe deux choses distinctes, et aucune d’elles n’est évidente à moins que vous ne la connaissiez déjà.

Tout d'abord, vous avez en réalité deux variables différentes:

  • La a dans votre première ligne est une variable globale (appelée ainsi parce qu'elle existe dans la portée globale, en dehors de toute définition de fonction).

  • La a dans les autres lignes est une variable locale, ce qui signifie qu'elle n'existe que dans votre fonction test().

Ces deux variables n'ont aucun lien l'une avec l'autre, même si elles portent le même nom.

Une variable est locale à une fonction s'il y a une instruction qui lui est assignée à l'intérieur de cette fonction - par exemple, votre ligne a = a +10.

Même dans ce cas, l'erreur semble toujours étrange - après tout, la toute première chose que vous faites dans test() est assignée à a, alors comment peut-on la référencer à l'avance?

La réponse est que, dans une instruction d'affectation, Python évalue tout ce qui se trouve à droite du signe = avant de l'attribuer au nom figurant à gauche - de sorte que même si l'affectation est écrite première dans votre code a obtient référencé premier dans ce côté droit: a +10.

Il y a deux façons de contourner ce problème. La première consiste à dire à Python que vous voulez vraiment que a dans test() soit identique à a dans la portée globale:

def test():
    global a
    a = a + 10
    print(a)

Cela fonctionnera, mais c’est un très mauvais moyen d’écrire des programmes. La modification des variables globales dans les fonctions devient difficile à gérer très rapidement, car vous avez généralement beaucoup de fonctions, et aucune d’entre elles ne peut jamais être sûre qu’une autre ne perturbe pas la variable globale d’une manière inattendue.

Un meilleur moyen est de passer des variables comme arguments à des fonctions, comme ceci:

a = 15

def test(x):
    x = x + 10
    print(x)

test(a)

Notez que le nom ne doit pas nécessairement être identique. Votre nouvelle définition de test() indique simplement qu’elle accepte une valeur et qu’elle fait ensuite quelque chose avec elle. Vous pouvez transmettre tout ce que vous voulez - il peut s'agir de a, ou du nombre 7, ou de quelque chose d'autre. En fait, votre code sera toujours plus facile à comprendre si vous essayez d'éviter d'avoir des variables du même nom dans des portées différentes.

Si vous jouez avec le code ci-dessus, vous remarquerez quelque chose d'intéressant:

>>> a = 15
>>> test(a)
25
>>> a
15

a n'a pas changé! En effet, bien que vous l'ayez transmise à test() et que celle-ci ait été affectée à x, il s'agissait alors de x qui a été modifié, laissant l'original a seul.

Si vous voulez réellement changer a, vous devez renvoyer votre x modifiée à partir de la fonction, puis le réaffecter à a à l'extérieur:

>>> a = 15
>>> 
>>> def test(x):
...     x = x + 10
...     print(x)
...     return x
... 
>>> a = test(a)
25
>>> a
25
23
Zero Piraeus

Vous modifiez une variable a créée dans le cadre de la fonction test(). Si vous voulez que la variable a soit modifiée, vous pouvez faire:

a = 15

def test():
    global a
    a = a + 1
    print(a)

test()
2
d4vsanchez

Je le ferais de cette façon:

def test(a):
    a = a +10
    return a

print(test(15))

Notez que dans la version proposée par la présente, il existe certaines différences par rapport à la vôtre.

Tout d’abord, ce que j’ai écrit créerait une fonction ayant pour entrée la valeur a (dans ce cas définie sur 15 lorsque nous appelons la fonction déjà définie dans la dernière ligne), puis affecte le objet a la valeur a (qui était 15) plus 10, puis retourne a (qui a été modifié et a maintenant 25 ans) et, enfin, imprime a out merci à la dernière ligne de code:

print(test(15))

Notez que ce que vous avez fait n'était pas réellement une fonction pure, pour ainsi dire. Généralement, nous voulons que les fonctions obtiennent une valeur d'entrée (ou plusieurs) et renvoient une valeur d'entrée (ou plusieurs). Dans votre cas, vous aviez une valeur d'entrée réellement vide et aucune valeur de sortie (car vous n'avez pas utilisé return ). De plus, vous avez essayé d’écrire cette entrée a en dehors de la fonction (ce qui, lorsque vous l’avez appelée en disant test(a) la valeur a n’a pas été chargé et vous a donné l’erreur -i aux yeux de l’ordinateur était vide").

De plus, je vous encourage à vous habituer à écrire return dans la fonction, puis à utiliser une impression lorsque vous l’appelez (comme je l’ai écrit dans la dernière ligne de codage: print(test(15))) au lieu de l’utiliser dans la fonction. Il est préférable d’utiliser print uniquement lorsque vous appelez la fonction et que vous voulez voir ce qu’elle fait réellement. 

Au moins, c'est la façon dont ils m'ont montré dans les leçons de programmation de base. Cela peut être justifié comme suit: si vous utilisez le retour dans la fonction, celle-ci vous donnera une valeur qui pourra être utilisée ultérieurement dans d'autres fonctions (c'est-à-dire la fonction return s avec laquelle vous pouvez travailler). Dans le cas contraire, vous n'obtiendrez qu'un nombre affiché à l'écran avec print , mais votre ordinateur ne pourra plus fonctionner avec.

P.S. Vous pouvez faire la même chose en faisant ceci:

def test(a):
    a +=10      
    return a

print(test(15))
2
americansanti

La portée de la variable est locale au bloc, sauf définition explicite à l'aide du mot clé global. Il existe un autre moyen d'accéder à la variable globale locale d'une fonction à l'aide de la fonction globals

a = 15

def test():
    a = globals()['a']
    a += 10
    print ( a )

test()

L'exemple ci-dessus imprimera 25 tout en conservant la valeur globale intacte, c'est-à-dire 15.

0
MaNKuR