1

Consider the following code:

def g():
    a = {}
    b = 0
    def f():
        a[0] = b
    f()
    print(a)
    return a
a = g()
print(a)

It gives the following output when executed:

{0: 0}
{0: 0}

But if I try to update b in f() as in

def g():
    a = {}
    b = 0
    def f():
        a[0] = b
        b+=1
    f()
    print(a)
    return a
a = g()
print(a)

It throws the following error:

UnboundLocalError: local variable 'b' referenced before assignment

Is this expected? I need to update b inside f(). Is that impossible?

Raghuram Vadapalli
  • 1,190
  • 2
  • 13
  • 27
  • https://stackoverflow.com/questions/929777/why-does-assigning-to-my-global-variables-not-work-in-python – DhruvPathak Sep 09 '17 at 19:32
  • Rather than trying to solve the apparent problem, I would suggest that you change your strategy so that you don't need to mutate non-local variables. Wherever possible, prefer pure functions. And if you do need to mutate, do it explicitly (passing the variables as function args) rather than indirectly. – FMc Sep 09 '17 at 19:38
  • Thanks @FMc, I will keep that in mind in future. – Raghuram Vadapalli Sep 09 '17 at 19:39
  • Impressive. Despite that this is a common duplicate, there were *four* duplicate answers marked on this question and *all* of them missed the mark. – Karl Knechtel Sep 09 '22 at 08:18

2 Answers2

2

Explicitly pass a and b to your function.

def g():
    a = {}
    b = 0
    def f(a, b):
        a[0] = b
        b += 1
        return b
    b = f(a, b)
    return a
Alexander
  • 105,104
  • 32
  • 201
  • 196
1

You need to use the nonlocal keyword:

def g():
    a = {}
    b = 0
    def f():
        nonlocal b
        a[0] = b
        b+=1
    f()
    print(a)
    return a
a = g()
print(a)

This is because b += 1 is equal to b = b + 1, so you're assigning b inside of the function f(). Even though it's later in the code, this will make it a local variable for the whole f() function, and thus a[0] = b will refer to the local b which isn't defined yet. Using nonlocal tells the interpreter that there's already a variable b and it should be used in the function, instead of creating a new local variable.

Markus Meskanen
  • 19,939
  • 18
  • 80
  • 119