Aha! conds = [ lambda msg, z = z: msg.hascode(z) for z in ("foo", "bar") ]
Is what I was looking for to explicitly use the value of z. What a caveat, didn't see that coming. Learning something new every day. Cheers, Joe Am 29.06.22 um 11:50 schrieb Johannes Bauer: > 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 -- https://mail.python.org/mailman/listinfo/python-list