How is `x = 42; x = lambda: x` parsed?
The variable x
is created by the first assignment, and rebound with the second assignment.
Since the x
in the lambda isn't evaluated until the lambda is called, calling it will evaluate to the most recently assigned value.
Note that this is not dynamic scoping - if it were dynamic, the following would print "99", but it prints "<function ...":
x = 42x = lambda: xdef test(f): x = 99 print(f())test(x)
The first assignment is irrelevant; the x
in the body of the lambda
is bound late:
x = lambda: x # no need for a prior assignmentx = lambda: y # notice: no NameError occurs, *until it is called*
This is the same reason that creating lambdas in a loop is tricky, and is also used to make trees with the standard library defaultdict
:
tree = lambda: defaultdict(tree)t = tree()t['foo']['bar']['baz'] = 'look ma, no intermediate steps'
A lambda is an anonymous function object. Python completely resolves whatever is on the right side of an equation to a single anonymous object and then resolves whatever is on the left side for assignment.
x = lambda: x
first compiles lambda: x
into a function object that returns whatever happens to be in x
at the time it is called. It then rebinds x
with this function object, deleting whatever object happened to be there before.
Now x
is a function that returns whatever is in x
... which is a function that returns whatever is in x
, etc... So you can write x()()()()()()
as many times as you want, and still get that orginal lambda:x
function object.
Python functions have a local namespace but only variables assigned in the function reside there. Since x
isn't assigned in the lambda
, it's resolved in the containing scope - that is, the module level "x". An identical piece of code is
def x(): return x
Contrast this with
def x(): x = 1 return x
Now, the parameter x
is a local variable and is unrelated to the global x
.