Why does the following code outputs 222 instead of 012? | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 4

Why does the following code outputs 222 instead of 012?

def cm(): return [lambda x:x*i for I in range(3)] for m in cm(): print(m(1), end="")

27th Oct 2019, 10:54 AM
Thimira Rathnayake
Thimira Rathnayake - avatar
7 Answers
+ 12
Let me rewrite the function regular style. def cm(): def f(x): return x*i l = [] for i in range(3): l.append(f) # i is 2 now return l The inner function f accesses i, but there is no i. So it has to get i from outside, from cm. But the function f will be returned from cm, and then cm has already ended. Now the i, which f is referring to, is lost. For this purpose, f has a special box __closure__ that 'remembers' the value i from cm. So f, exported three times within l to the outermost scope, accesses the last value it remembers from when i still existed. And that was 2.
27th Oct 2019, 11:24 AM
HonFu
HonFu - avatar
+ 5
https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result
27th Oct 2019, 11:04 AM
R_3-dr
R_3-dr - avatar
+ 5
These are my thoughts about this program: Function cm returns a list, containing the function cm, local variables, a list comprehension and a lambda function. As cm runs in a loop controlled by a range object, the returned list contains this information 3 times, each having an individual object id: if you store the returned "values" in a variable res, you can see what happens: >>> res = cm) <class 'list'> >>> res [<function cm.<locals>.<listcomp>.<lambda> at 0x66bb7c4>, <function cm.<locals>.<listcomp>.<lambda> at 0x66bb41c>, <function cm.<locals>.<listcomp>.<lambda> at 0x66bb2fc>] >>> res[0](1) 2 >>> res[1](1) 2 >>> res[2](1) 2 The calculated values returned by the lamba function depends on the max value of the range object and the value passed to the lambda function. The function cm uses only the last calculated value, which is 2 in our case and repaeted it 3 times. You can play around this by changing the max value of the range object, and / or the value passed to the function cm
14th Jan 2020, 10:13 AM
Lothar
Lothar - avatar
+ 1
“Closure [...] refers to values needed by the function but are taken from the surrounding scope.” https://stackoverflow.com/questions/14413946/what-exactly-is-contained-within-a-obj-closure
14th Jan 2020, 5:26 AM
Prof. Dr. Zoltán Vass
+ 1
HonFu thank you
29th Jan 2020, 11:38 PM
Aymen
0
Jan Markus, can you please explain where the fault in code is?
27th Oct 2019, 11:19 AM
Thimira Rathnayake
Thimira Rathnayake - avatar
0
Sudden Lee Thank you so much, official answers are so precious.
29th Jan 2020, 11:41 PM
Aymen