Creating lambdas inside generator expression

Johannes Bauer dfnsonfsduifb at gmx.de
Wed Jun 29 05:50:36 EDT 2022


Hi list,

I've just encounted something that I found extremely unintuitive and
would like your feedback. This bit me *hard*, causing me to question my
sanity for a moment. Consider this minimal example code (Py 3.10.4 on
Linux x64):


class Msg():
	def hascode(self, value):
		print("Check for", value)
		return False

conds = [
	lambda msg: msg.hascode("foo"),
	lambda msg: msg.hascode("bar"),
]

msg = Msg()
print(conds[0](msg))
print(conds[1](msg))



It works perfectly and does exactly what it looks like. The output is:

Check for foo
False
Check for bar
False

But now consider what happens when we create the lambdas inside a list
comprehension (in my original I used a generator expresison, but the
result is the same). Can you guess what happens when we create conds
like this?

conds = [ lambda msg: msg.hascode(z) for z in ("foo", "bar") ]

I certainly could not. Here's what it outputs:

Check for bar
False
Check for bar
False

I.e., the iteration variable "z" somehow gets bound inside the lambda
not by its value, but by its reference. All checks therefore refence
only the last variable.

This totally blew my mind. I can understand why it's happening, but is
this the behavior we would expect? And how can I create lambdas inside a
generator expression and tell the expression to use the *value* and not
pass the "z" variable by reference?

Cheers,
Joe


More information about the Python-list mailing list