I encountered such an interview question :
Tell the output of the following snippet:
def num():
return [lambda x:i*x for i in range(4)]
print([m(2)for m in num()])
I thought it simple and guessed [0, 2, 4, 6]
Unfortunately
In [1]: def num():
...: return [lambda x:i*x for i in range(4)]
In [2]: print([m(2) for m in num()])
[6, 6, 6, 6]
Review its details
In [5]: for _ in num():
...: print(_)
...:
<function num.<locals>.<listcomp>.<lambda> at 0x7f042411dc80>
<function num.<locals>.<listcomp>.<lambda> at 0x7f0424182378>
<function num.<locals>.<listcomp>.<lambda> at 0x7f04240dfc80>
<function num.<locals>.<listcomp>.<lambda> at 0x7f042410ed08>
What's the name of such an obscure grammar to define a num,
How could it output such a rusult as [6, 6, 6,6]
I read the python - Lambdas inside list comprehensions - Stack Overflow
>>> y = 3
>>> f = lambda: y
>>> f()
3
>>> y = 4
>>> f()
4
Put it in a standard way
In [15]: def foo(): return x
In [16]: x = 1; foo()
Out[16]: 1
In [17]: x = 4; foo()
Out[17]: 4
The explanation is not conceivable which does not illustrate closure.
the wikipedia's answer is better to take it as an obscure usage of closure to shadow vaiable
This can also be achieved by variable shadowing (which reduces the scope of the non-local variable), though this is less common in practice, as it is less useful and shadowing is discouraged. In this example f can be seen to be a closure because x in the body of f is bound to the x in the global namespace, not the x local to g:
Closure (computer programming) - Wikipedia
x = 0
def f(y):
return x + y
def g(z):
x = 1 # local x shadows global x
return f(z)
g(1) # evaluates to 1, not 2