345 votes

Utilisation du mot-clé "global" en Python

D'après ce que j'ai compris, Python dispose d'un espace de noms distinct pour les fonctions, donc si je veux utiliser une variable globale dans une fonction, je devrais probablement utiliser global .

Cependant, j'ai été en mesure d'accéder à une variable globale même sans global :

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Est-ce que je rate quelque chose ? En outre, ce qui suit est tiré de la documentation Python :

Noms listés dans une déclaration globale ne doivent pas être définis comme des paramètres formels ou dans une boucle de contrôle for cible, définition de classe, fonction ou une déclaration d'importation.

Si les paramètres formels et la définition de la classe me paraissent logiques, je ne comprends pas la restriction concernant la cible de contrôle de la boucle for et la définition de la fonction.

2 votes

Je pense que vous confondez avec php qui requiert l'utilisation du mot-clé global - les docs de python le confirment - en gros, si ce n'est pas défini dans le contexte local, c'est traité comme global.

14 votes

Faites attention à votre formulation : Python n'a pas d'espace de nom séparé pour les fonctions (cela signifierait que vous pourriez avoir def foo(): ... y foo = ... en même temps). Il crée une nouvelle portée pour chaque appel de fonction. (Mais en quoi cela est-il différent d'à peu près tous les autres langages de haut niveau éloignés dans le monde).

434voto

Unode Points 2299

Le mot-clé global n'est utile que pour modifier ou créer des variables globales dans un contexte local, bien que la création de variables globales soit rarement considérée comme une bonne solution.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Ce qui précède vous donnera :

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

Alors que si vous utilisez le global la variable devient disponible "en dehors" de la portée de la fonction, devenant ainsi une variable globale.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Donc le code ci-dessus vous donnera :

locally defined
locally defined

En outre, en raison de la nature de python, vous pourriez également utiliser global pour déclarer des fonctions, des classes ou d'autres objets dans un contexte local. Cependant, je vous le déconseille car cela provoque des cauchemars si quelque chose ne va pas ou nécessite un débogage.

75 votes

Le terme "global" dans ce contexte semble être différent de ce que d'autres langues considèrent comme "global". En Python, une référence "globale" reste dans les limites du module et doit être référencée depuis l'extérieur de ce module sous la forme "module.global_var" plutôt que simplement "global_var" comme on pourrait s'y attendre.

20 votes

@juice - En Python, il n'y a pas d'absolu. globals automatiquement définis dans tous les espaces de noms (heureusement). Comme vous l'avez correctement souligné, un global est lié à un espace de nom au sein d'un module, mais il peut être importé dans un autre module en tant que from module import variable o import module.variable . Dans le premier cas, l'importation rendrait la variable accessible en tant que variable sans exiger de référence comme module. . S'il est considéré comme global, la portée du module dépendra de l'endroit où il est importé. Voir également nonlocal comme nouveau mot-clé lié à la portée dans python 3.

5 votes

Pourriez-vous expliquer pourquoi les variables globales ne sont pas une bonne solution ? J'entends souvent cela, mais dans mon projet actuel, elles semblent faire exactement ce dont j'ai besoin. Y a-t-il quelque chose de plus sinistre auquel je n'ai pas pensé ?

253voto

Ivo Wetzel Points 27802

Bien que vous puissiez accéder aux variables globales sans l'option global si vous voulez les modifier, vous devez utiliser le mot-clé global mot-clé. Par exemple :

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

Dans votre cas, vous accédez simplement à la liste sub .

7 votes

Avec un avertissement : foo = 3 sans travail global, mais foo est à nouveau défini localement dans blub la portée de la fonction et ne modifie pas la variable originale foo. C'était assez déroutant pour moi.

2 votes

@chhantyal si par "fonctionne" vous voulez dire qu'il ne lève pas d'erreur, vous avez raison, mais dans le contexte d'Ivo Wetzel, il ne fonctionnerait pas comme prévu. Il y a des utilisations pour un tel comportement, mais ce n'est souvent pas ce que le programmeur veut.

0 votes

Quelqu'un peut-il expliquer le commentaire de @chhantyal ou @democidist ? Lorsque j'essaie ce code (avec Python 3) et que j'appelle blub() le foo en dehors de la fonction est liée à 3, comme prévu.

89voto

pycruft Points 8095

C'est la différence entre l'accès, le nom et la liaison à l'intérieur d'un champ.

Si vous êtes simplement à la recherche d'un variable pour lire sa valeur, vous avez accès au niveau mondial ainsi qu'une portée locale.

Toutefois, si vous affecter à une variable dont le nom n'est pas dans la portée locale, vous êtes à la liaison de ce nom dans ce champ (et si ce nom existe également en tant que global, vous aurez le cacher).

Si vous voulez être en mesure d'attribuer le nom global, vous devez dire à l'analyseur à l'utilisation de la dénomination globale plutôt que de lier un nouveau nom local - qui est ce que le "global" mot-clé.

La liaison n'importe où à l'intérieur d'un bloc fait que le nom partout dans ce bloc à être liés, ce qui peut provoquer certaines plutôt bizarre, conséquences (p. ex. UnboundLocalError soudainement apparaître précédemment code de travail).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

2 votes

Très contre-intuitif, difficile de croire que c'est du code python valide

61voto

kindall Points 60645

Les autres réponses répondent à votre question. Une autre chose importante à savoir sur les noms en Python est qu'ils sont soit locaux, soit globaux sur une base per-scope.

Considérez ceci, par exemple :

value = 42

def doit():
    print value
    value = 0

doit()
print value

Vous pouvez probablement deviner que le value = 0 sera affectée à une variable locale et n'affectera pas la valeur de la même variable déclarée en dehors de l'instruction doit() fonction. Vous serez peut-être plus surpris de découvrir que le code ci-dessus ne fonctionnera pas. La déclaration print value à l'intérieur de la fonction produit un UnboundLocalError.

La raison en est que Python a remarqué que, ailleurs dans la fonction, vous attribuez le nom value et aussi value n'est déclaré nulle part global . Cela en fait une variable locale. Mais lorsque vous essayez de l'imprimer, le nom local n'a pas encore été défini. Python dans ce cas ne retombe pas plutôt que de rechercher le nom en tant que variable globale, comme le font certains autres langages. En fait, vous ne pouvez pas accéder à une variable globale si vous avez défini une variable locale du même nom. partout dans la fonction.

2 votes

Merci de le signaler. Donc, tant que votre portée locale n'assigne pas à un nom qui existe en dehors d'elle, les références dans la portée locale utiliseront le nom extérieur. Cependant, si vous assignez ce nom à n'importe quel endroit de votre fonction, les références dans cette portée locale, même avant l'assignation locale, ne regardent pas à l'extérieur.

1 votes

Exactement, tu l'as. global (ou nonlocal dans Python 3.x) annule ce comportement et vous permet de réassigner le nom externe.

2 votes

Dans d'autres langues, cela semble être désigné par le terme "hissage", comme ceci par exemple : github.com/shichuan/javascript-patterns/blob/master/

17voto

user225312 Points 22699

Accéder à un nom et attribuer un nom sont deux choses différentes. Dans votre cas, vous accédez simplement à un nom.

Si vous assignez une variable dans une fonction, cette variable est supposée être locale à moins que vous ne la déclariez globale. En l'absence de déclaration, elle est considérée comme globale.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X