Is there "let binding" in Python?

Jeff Epler jepler at unpythonic.net
Sun Sep 14 22:14:44 EDT 2003


For more information about Python's scoping rules, you can read parts of
the tutorial and language reference.  Here are some relevant URLs:

Tutorial
9.2 Python Scopes and Name Spaces
http://www.python.org/doc/tut/node11.html#SECTION0011200000000000000000

Language Reference
4.1 Naming and binding
http://www.python.org/doc/ref/naming.html

The rules are pretty simple, which probably means they're too simple to
do whatever you're trying to explain about Scheme.

You can write

    def outer():
        x = 3
        def f(arg): return arg * x
        return f(5)

to have outer() return 15,  but you can't write

    def outer():
        x = 3
        def f(arg): return arg * x
        x = 4
        return f(5)

to have outer() return 15, because 'f' will take the value of x from the
enclosing scope, and that value is 4 at the time of the call.

If you want to have f capture the value of x at that moment, you must
manually introduce another layer of nesting:

    def outer():
        x = 3
        def inner(x):
            def f(arg): return arg*x
            return f
        f = inner(x)
        x = 4
        return f(5)

or you can try to structure your code so that you can avoid re-using the
name 'x'.  One common example of a situation where you can't avoid it
is something like this:

    from Tkinter import *

    def button_func(i):
        print "pressed button", i

    def make_stupid_gui():
        t = Tk()
        for i in range(10):
            b = Button(t, text="Button #%d" % i,
                command=lambda: button_func(i))
            b.pack() 
    make_stupid_gui()

Instead, you must write

    def make_stupid_gui():
        t = Tk()
        for i in range(10):
            def make_binding(i):
                return lambda: button_func(i)
            b = Button(t, text="Button #%d" % i,
                command=make_binding(i))
            b.pack() 

A programmer who is more comfortable with objects than with lambdas
might write something like this instead

    class ButtonCallback:
        def __init__(self, i): self.i = i
        def __call__(self, i): print "pressed button", i

    def make_stupid_gui():
        t = Tk()
        for i in range(10):
            b = Button(t, text="Button #%d" % i,
                command=ButtonCallback(i))
            b.pack() 
    make_stupid_gui()

> PS: I'm a newbie, so the answer in fact might be super-easy.

Not an answer, but advice: when writing programs in Python, write Python
programs.  If it's your task to translate some Scheme (or any other
language) into Python as literally as possible, my heart goes out to you.

Jeff





More information about the Python-list mailing list