selfboot / AnnotatedShadowSocks

Annotated shadowsocks(python version)
Other
3 stars 1 forks source link

Keyword which are not often used: global vs nonlocal #34

Open selfboot opened 7 years ago

selfboot commented 7 years ago

global

The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. While using global names is automatic if they are not defined in the local scope, assigning to global names would be impossible without global.

If a name is declared global, then all references and assignments go directly to the middle scope containing the module’s global names. Otherwise, all variables found outside of the innermost scope are read-only (an attempt to write to such a variable will simply create a new local variable in the innermost scope, leaving the identically named outer variable unchanged).

Look at the demo:

a = 0
b = 1
def func():
    print a
    print b
    b = 4

func()

With the statement b = 4 commented out, this code outputs 0 1, just what you'd expect. But if you uncomment that line, on the line print b, you get the error UnboundLocalError: local variable 'b' referenced before assignment.

This is because during static analysis, the interpreter determines that b is assigned to in func, and that it is therefore a local variable of inner. The print line attempts to print the b in that func scope before it has been assigned.

We can use global b to declare that b is the global variable.

a = 0
b = 1
def func():
    global b
    print a
    print b
    b = 4

func()

nonlocal

Global is not enough actually, suppose I have the following python code:

string = "global"
def outer():
    string = "enclosed"
    def inner():
        # global string
        string = "String was changed by a nested function!"
    inner()
    return string

print outer()

It will print enclosed. What if I want the string in function outer to be changed within nested function inner. Add 'global string' can't work, this will modify the global variable. In Python 3.x, you can use the nonlocal keyword:

string = "global"
def outer():
    string = "enclosed"
    def inner():
        nonlocal string
        string = "String was changed by a nested function!"
    inner()
    return string

print(outer())

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

Ref

33

Python Scopes and Namespaces
Python overwriting variables in nested functions
Using global variables in a function other than the one that created them