1

The following program gives me the error:

NameError: name 'n' is not defined

def g():
    n=7
    def f():
        global n
        if n==7:
            n=7
    return f()
g()

Can anybody help me understand what does that mean?

  • 1
    Is `n` actually supposed to be global? Because it looks more like it's a local variable of `g`, which would make it `nonlocal` in `f`, not global. See https://stackoverflow.com/q/2609518/38906320 – khelwood May 11 '21 at 23:47
  • It means exactly what it says, when you hit the line `if n==7` *there is no globally defined `n`*. In this case, use `nonlocal` – juanpa.arrivillaga May 12 '21 at 00:03

2 Answers2

2

Insert a global in your g() function.

def g():
    global n
    n=7
    def f():
        global n
        if n==7:
            n=7
    return f()
g()

An even more simplified version of when this can occur is this.

n = 10
def g():
    n+=1
g()

You can't modify n right now. But if we add global inside the function like so

n = 10
def g():
    global n
    n+=1
g()
print(n)

we get the expected output

11

But one thing to remember is we don't have to add global if all we are doing is printing the variable.

Buddy Bob
  • 5,829
  • 1
  • 13
  • 44
0

Somewhat broadly: don't do this
..and try to make your scopes as obvious as possible!

Often this is a case for a new class or a dict (which is already global and mutable when created at the global scope)

shared = {}

def a():
    shared['x'] = 5
    def inner():
        if shared.get('x') == 5:
            shared['x'] = 6
        print(shared['x'])
    inner()

a()
% python3 test.py
6

The problem is that global n refers to the global scope, not g's scope (which f already has access to unless it modifies n)

This can lead to some surprising results

#!/usr/bin/env python3
# test.py
def a():
    x = 1
    def display():
        print(x)
    display()

def b():
    x = 1
    def display():
        print(x)
        x = 1
    display()

a()
b()
% python3 test.py
1
Traceback (most recent call last):
  File "test.py", line 17, in <module>
  File "test.py", line 14, in b
  File "test.py", line 12, in display
UnboundLocalError: local variable 'x' referenced before assignment
ti7
  • 16,375
  • 6
  • 40
  • 68
  • no, use `nonlocal` – juanpa.arrivillaga May 12 '21 at 00:04
  • @juanpa.arrivillaga "oh, yuck"; perfectly valid use (and actually new to me, [despite being new in 3.0](https://www.python.org/dev/peps/pep-3104/) - thanks!) .. but I really want a core of this answer to be that potentially-confusing scope should be considered improper over using a keyword to clarify it! – ti7 May 12 '21 at 00:44