Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone please explain this bit of Python code?

I started working in Python just recently and haven't fully learned all the nuts and bolts of it, but recently I came across this post that explains why python has closures, in there, there is a sample code that goes like this:

y = 0

def foo():
    x = [0]
    def bar():
        print x[0], y
    def change(z):
        global y
        x[0] = y = z

    change(1)
    bar()
    change(2)
    bar()
    change(3)
    bar()
    change(4)
    bar()

foo()

1 1
2 2
3 3

and basically I don't understand how it actually works, and what construct like x[0] does in this case, or actually I understand what it's doing, I just don't get how is it this :)

like image 657
Alex N. Avatar asked Jul 31 '10 03:07

Alex N.


1 Answers

Before the nonlocal keyword was added in Python 3 (and still today, if you're stuck on 2.* for whatever reason), a nested function just couldn't rebind a local barename of its outer function -- because, normally, an assignment statement to a barename, such as x = 23, means that x is a local name for the function containing that statement. global exists (and has existed for a long time) to allow assignments to bind or rebind module-level barenames -- but nothing (except for nonlocal in Python 3, as I said) to allow assignments to bind or rebind names in the outer function.

The solution is of course very simple: since you cannot bind or rebind such a barename, use instead a name that is not bare -- an indexing or an attribute of some object named in the outer function. Of course, said object must be of a type that lets you rebind an indexing (e.g., a list), or one that lets you bind or rebind an attribute (e.g., a function), and a list is normally the simplest and most direct approach for this. x is exactly that list in this code sample -- it exists only in order to let nested function change rebind x[0].

like image 148
Alex Martelli Avatar answered Oct 05 '22 00:10

Alex Martelli