I have code with labdas, I have checked each time the function object is created it is different (not reference to same object), but it doesn't work as I would expect it. Is there any way how to or I should use a functor to do it even if I have constant data which I insert into lambda`s body?
pairs = [('abc', 'xyz'), ('123', '987'), ('abc', '987')]
pairLambs = []
for p in pairs:
pairLambs.append(lambda: print(p))
pairLambs[0]()
pairLambs[1]()
pairLambs[2]()
outputs:
('abc', '987')
('abc', '987')
('abc', '987')
but I need:
('abc', 'xyz')
('123', '987')
('abc', '987')
This is a well-known gotcha - since you don't bind the current value of p
when defining the lambda
, when called it uses the current value of p
. The solution is to use a named arg with default value to bind the "current" (definition time) value of p
:
pairs = [('abc', 'xyz'), ('123', '987'), ('abc', '987')]
pairLambs = []
for p in pairs:
pairLambs.append(lambda p=p: print(p))
pairLambs[0]()
pairLambs[1]()
pairLambs[2]()
If you want to 'specialize' function, you should take a look at functools
:
import functools
pairs = [('abc', 'xyz'), ('123', '987'), ('abc', '987')]
pairLambs = []
for p in pairs:
pairLambs.append(functools.partial(print, p))
This gives result you expect.
This is how closures in python work. To achive what you want you can do this:
for p in pairs:
def closure(_p):
return lambda: print(_p)
pairLambs.append(closure(p))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With