Search code examples
pythonclosuresnested-function

Does Python not support closures unlike Lua?


I was learning about closures in Lua and came accross this code that works in Lua:

function newcounter()
    local i = 0
    function dummy()
        i = i + 1
        return i
    return dummy

x = newcounter()
print(x())
-- this outputs 1, i.e., dummy uses the i variable from its enclosing function newcounter

I thought Python also supports a similar closure. So I tried the following code in Python3:

def nc():
    i = 0
    def dummy():
        i = i + 1
        return i
    return dummy

x = nc()
print(x())

However, when I run the above Python code, I get the error that i is accessed before being assigned!

Traceback (most recent call last):
  File "/tmp/test.py", line 9, in <module>
     print(x())
  File "/tmp/test.py", line 4, in dummy
     i = i + 1
UnboundLocalError: local variable 'i' referenced before assignment

Does this mean Python does not support closures? Or am I misunderstanding something about closures?


Solution

  • Python decides the scope of variables based on where it finds assignments to them. Because you have an assignment to i in the form i = ..., i will be a local variable scoped to dummy by default, but you can override that with a nonlocal statement:

    def nc():
        i = 0
        def dummy():
            nonlocal i
            i = i + 1
            return i
        return dummy
    
    x = nc()
    print(x())

    So yes, Python has closures.