Python closure: Why changing dictionary in closure is allowed while changing numbers isn't?

Viewed 28

this code works well when I try to change dictionary in closure

def a():
    x = {'a':'b'}
    def b():
        x['a'] = 'd'
        print(x)
    return b
>>> b = a()
>>> b()
{'a':'d'}

output is meeting my expectation. but why the code below doesn't work?

def m():
x = 1
def n():
    x += 1
    print(x)
return n
>>> n = m()
>>> n()

UnboundLocalError: local variable 'x' referenced before assignment

Honestly, I've known that we can use nonlocal x statement to solve this problem
But can anybody explain the reason more deeply for me? what the difference between a dictionary and a number
Thanks!

1 Answers

Python has a great FAQ specifically on this.

In short, when you modify a dictionary, or any mutable object, you modify the same object, so you don't re-assign the variable. In case of an integer, since it's immutable, by doing a += you create a new object and put it into x. Since x is now defined inside the inner function, but you're trying to bring data from the outer function, you have an issue.

You can check if it's the same object using id().

Related