DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on

global vs nonlocal in Python (10)

Buy Me a Coffee

*Memo:

With 2 functions or generators, there are 3 kinds of variables from the viewpoint of second() as shown below:

*Memo:

  • A global variable is the variable out of any functions and classes.
  • A non-local variable is the variable within outer functions.
  • A local variable is the variable which is within its function.
  • A global and non-local variable can be accessed from a function or generator as long as the function or generator is called and run after them even if the function or generator is defined before them.

<Function>:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        v = 4 # <- local variable
        print(v) # 4
        return 3
    v = second # <- Non-local variable
    print(v()) # 3
    return 2
v = first # <- Global variable
print(v()) # 2
Enter fullscreen mode Exit fullscreen mode

<Generator>:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        v = 4 # <- local variable
        print(v) # 4
        yield 3
    v = second() # <- Non-local variable
    print(next(v)) # 3
    yield 2
v = first() # <- Global variable
print(next(v)) # 2
Enter fullscreen mode Exit fullscreen mode

A global statement can refer to a global variable as shown below:

*Memo:

  • The doc explains the rules for local and global variables in Python.

<Function>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v
        print(v.__name__) # first
    v = second # <- ✖
    v()
    print(v.__name__) # second
v = first # <- 〇
v()
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
    v = second # <- ✖
    v()
    print(v.__name__) # second
v = first # <- 〇
v()
print(v.__name__) # Hello
Enter fullscreen mode Exit fullscreen mode

<Generator>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v
        print(v.__name__) # first
        yield
    v = second() # <- ✖
    next(v)
    print(v.__name__) # second
    yield
v = first() # <- 〇
next(v)
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
        yield
    v = second() # <- ✖
    next(v)
    print(v.__name__) # second
    yield
v = first() # <- 〇
next(v)
print(v.__name__) # Hello
Enter fullscreen mode Exit fullscreen mode

A nonlocal statement can refer to a non-local variable as shown below:

<Function>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v
        print(v.__name__) # second
    v = second # <- 〇
    v()
    print(v.__name__) # second
v = first # <- ✖
v()
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
    v = second # <- 〇
    v()
    print(v.__name__) # Hello
v = first # <- ✖
v()
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

<Generator>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v
        print(v.__name__) # second
        yield
    v = second() # <- 〇
    next(v)
    print(v.__name__) # second
    yield
v = first() # <- ✖
next(v)
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
        yield
    v = second() # <- 〇
    next(v)
    print(v.__name__) # Hello
    yield
v = first() # <- ✖
next(v)
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Without a global or nonlocal statement, the closest non-local variable or a global variable can be referred to in order as shown below:

<Function>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        print(v.__name__) # second
    v = second # <- 〇
    v()
    print(v.__name__) # second
v = first # <- ✖
v()
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
    v = second # <- 〇
    v()
    print(v.__name__) # Hello
v = first # <- ✖
v()
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

<Generator>:

Read:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        print(v.__name__) # second
        yield
    v = second() # <- 〇
    next(v)
    print(v.__name__) # second
    yield
v = first() # <- ✖
next(v)
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Change:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        v.__name__ = 'Hello'
        print(v.__name__) # Hello
        yield
    v = second() # <- 〇
    next(v)
    print(v.__name__) # Hello
    yield
v = first() # <- ✖
next(v)
print(v.__name__) # first
Enter fullscreen mode Exit fullscreen mode

Using both a global and nonlocal statement in the same function or generator gets error as shown below:

<Function>:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v # SyntaxError: name 'v' is nonlocal and global
        nonlocal v
        print(v.__name__)
    v = second # <- ✖
    v()
    print(v.__name__)
v = first # <- ✖
v()
print(v.__name__)
Enter fullscreen mode Exit fullscreen mode
""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v # SyntaxError: name 'v' is nonlocal and global
        global v
        print(v.__name__)
    v = second # <- ✖
    v()
    print(v.__name__)
v = first # <- ✖
v()
print(v.__name__)
Enter fullscreen mode Exit fullscreen mode

<Generator>:

""" It's from the viewpoint of `second()` """

def first():
    def second():
        global v # SyntaxError: name 'v' is nonlocal and global
        nonlocal v
        print(v.__name__)
        yield
    v = second() # <- ✖
    next(v)
    print(v.__name__)
    yield
v = first() # <- ✖
next(v)
print(v.__name__)
Enter fullscreen mode Exit fullscreen mode
""" It's from the viewpoint of `second()` """

def first():
    def second():
        nonlocal v # SyntaxError: name 'v' is nonlocal and global
        global v
        print(v.__name__)
        yield
    v = second() # <- ✖
    next(v)
    print(v.__name__)
    yield
v = first() # <- ✖
next(v)
print(v.__name__)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)