It’s possible to use nonlocal in Python 3 to modify the scope of a variable within a closure. In the example below, we’re basically poking a hole in the increment function scope for the variable test. Since test is bound to the counter function it will continue to be accessible after c = counter() has finished executing, but only within the scope of increment.

def counter():
    test = 0
    def increment():
        nonlocal test
        test += 1
        return test
    return increment

c = counter()
print(c()) # returns 1
print(c()) # returns 2
print(c()) # returns 3

print(c.__closure__[0].cell_contents)

Why is this? Going into further detail requires reviewing what a closure specifically is.

In the simplest case, it’s nothing more than a function (say for example, product())) defined as a veriable within another function (say, creator()) where the enclosed function product is enclosed by creator. The function product, in this case, is returned to the scope of creator. The function product has access to the variables defined within the scope of creator.

def creator():
    def product():
        foo = 'created within product'
        return foo
    
    return product

product_object = creator()
print(product_object())    # prints "created within product"