Python Language Portée locale vs globale


Exemple

Quelle est la portée locale et globale?

Toutes les variables Python accessibles à un moment donné dans le code sont de portée locale ou globale .

L'explication est que la portée locale inclut toutes les variables définies dans la fonction en cours et que la portée globale inclut les variables définies en dehors de la fonction en cours.

foo = 1  # global

def func():
    bar = 2  # local
    print(foo)  # prints variable foo from global scope
    print(bar)  # prints variable bar from local scope

On peut inspecter quelles variables sont dans quelle portée. Les fonctions intégrées locals() et globals() renvoient l'ensemble des étendues en tant que dictionnaires.

foo = 1

def func():
    bar = 2
    print(globals().keys())  # prints all variable names in global scope
    print(locals().keys())  # prints all variable names in local scope

Que se passe-t-il avec les conflits de noms?

foo = 1

def func():
    foo = 2  # creates a new variable foo in local scope, global foo is not affected

    print(foo)  # prints 2

    # global variable foo still exists, unchanged:
    print(globals()['foo'])  # prints 1
    print(locals()['foo'])  # prints 2

Pour modifier une variable globale, utilisez le mot-clé global :

foo = 1

def func():
    global foo
    foo = 2  # this modifies the global foo, rather than creating a local variable

La portée est définie pour tout le corps de la fonction!

Cela signifie qu'une variable ne sera jamais globale pour la moitié de la fonction et locale par la suite, ou inversement.

foo = 1

def func():
    # This function has a local variable foo, because it is defined down below.
    # So, foo is local from this point. Global foo is hidden.

    print(foo) # raises UnboundLocalError, because local foo is not yet initialized
    foo = 7
    print(foo)

De même, l'opposite:

foo = 1

def func():
    # In this function, foo is a global variable from the begining

    foo = 7  # global foo is modified

    print(foo)  # 7
    print(globals()['foo'])  # 7

    global foo  # this could be anywhere within the function
    print(foo)  # 7

Fonctions dans les fonctions

Il peut exister de nombreux niveaux de fonctions imbriquées dans les fonctions, mais au sein d’une même fonction, il n’ya qu’une seule portée locale pour cette fonction et la portée globale. Il n'y a pas de portées intermédiaires.

foo = 1

def f1():
    bar = 1

    def f2():
        baz = 2
        # here, foo is a global variable, baz is a local variable
        # bar is not in either scope
        print(locals().keys())  # ['baz']
        print('bar' in locals())  # False
        print('bar' in globals())  # False

    def f3():
        baz = 3
        print(bar)  # bar from f1 is referenced so it enters local scope of f3 (closure)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

    def f4():
        bar = 4  # a new local bar which hides bar from local scope of f1
        baz = 4
        print(bar)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

global vs nonlocal (Python 3 uniquement)

Ces deux mots-clés sont utilisés pour obtenir un accès en écriture aux variables qui ne sont pas locales pour les fonctions en cours.

Le mot-clé global déclare qu'un nom doit être traité comme une variable globale.

foo = 0  # global foo

def f1():
    foo = 1  # a new foo local in f1
    
    def f2():
        foo = 2  # a new foo local in f2
        
        def f3():
            foo = 3  # a new foo local in f3
            print(foo)  # 3
            foo = 30  # modifies local foo in f3 only
        
        def f4():
            global foo
            print(foo)  # 0
            foo = 100  # modifies global foo

D'un autre côté, nonlocal (voir Variables nonlocal ), disponible dans Python 3, prend une variable locale d'une portée englobante dans la portée locale de la fonction actuelle.

De la documentation Python sur nonlocal :

L'instruction nonlocal fait que les identificateurs répertoriés font référence aux variables précédemment liées dans la portée englobante la plus proche, à l'exception des globales.

Python 3.x 3.0
def f1():
    
    def f2():
        foo = 2  # a new foo local in f2

        def f3():
            nonlocal foo  # foo from f2, which is the nearest enclosing scope
            print(foo)  # 2
            foo = 20  # modifies foo from f2!