This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: unusual behaviour on list of dependable lambdas
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.8, Python 3.7, Python 3.6, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Alexey Burdin, tim.peters, veky, xtreak
Priority: normal Keywords:

Created on 2019-11-27 21:22 by Alexey Burdin, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg357586 - (view) Author: Alexey Burdin (Alexey Burdin) Date: 2019-11-27 21:22
>>> x=[2,3]
>>> [f(x) for f in [(lambda a:a[i]) for i in [0,1]]]
[3, 3]
>>> [f(x) for f in [lambda a:a[0],lambda a:a[1]]]
[2, 3]
msg357587 - (view) Author: Alexey Burdin (Alexey Burdin) Date: 2019-11-27 21:24
x=[2,3]
[f(x) for f in [(lambda a:a[i]) for i in [0,1]]]
#the expected output is [2,3] but actual is [3,3]
[f(x) for f in [lambda a:a[0],lambda a:a[1]]]
#results [2,3] normally
msg357605 - (view) Author: Vedran Čačić (veky) * Date: 2019-11-28 06:07
Why exactly is [2,3] expected? In the first example, the inner list has two functions that are _exactly the same_. Each of them takes a, grabs i from outer scope, and returns a[i]. (And of course, at the moment of evaluation of these functions, i is 1.) 

Do you really expect i to be "spliced" into the lambda as a value at the moment of constructing the function? Would you also expect

lambda x: x + input('y? ')

to ask you for input?
msg357607 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-11-28 06:18
This could also help in understanding late binding that happens with the lambdas in the report : https://docs.python-guide.org/writing/gotchas/#late-binding-closures
msg357612 - (view) Author: Vedran Čačić (veky) * Date: 2019-11-28 08:26
Yes, I never really understood what problem people have with it. If I manually say

i = 0
f = lambda a: a[i]
i = 1
g = lambda a: a[i]

why does anyone expect functions f and g to be different? They have the same argument, and do the same thing with it. The bytecode is completely the same. How can they do different things?
msg357628 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2019-11-28 19:04
This behavior is intended and expected, so I'm closing this.

As has been explained, in any kind of function (whether 'lambda' or 'def'), a non-local variable name resolves to its value at the time the function is evaluated, not the value it _had_ at the time the function was defined.

If you need to use bindings in effect at the time the function is defined, then you need to do something to force that to happen.  A common way is to abuse Python's default-argument mechanism to initialize a local argument to the value of a non-local variable at function definition time.  In practice, e.g., this means changing the

    lambda a:

in your first example to

    lambda a, i=i:

Then, when the lambda is defined ('lambda' and 'def' are executable statements in Python! not just declarations), the then-current binding of non-local variable 'i' is captured and saved away as the default value of the local argument name 'i'.
History
Date User Action Args
2022-04-11 14:59:23adminsetgithub: 83114
2019-11-28 19:04:45tim.peterssetstatus: open -> closed

nosy: + tim.peters
messages: + msg357628

resolution: not a bug
stage: resolved
2019-11-28 08:26:47vekysetmessages: + msg357612
2019-11-28 06:18:23xtreaksetnosy: + xtreak
messages: + msg357607
2019-11-28 06:07:09vekysetnosy: + veky
messages: + msg357605
2019-11-27 21:24:49Alexey Burdinsetmessages: + msg357587
2019-11-27 21:22:03Alexey Burdincreate