You loop to avoid writing something like this:
lis.append( lambda: 0 )
lis.append( lambda: 1 )
lis.append( lambda: 2 )
Your intention is to write lambda functions that return constant integers. But you are defining and appending a function that is returning object i
. Thus the 3 appended functions are the same.
The byte code behind the functions created returns i
:
In [22]: import dis
In [25]: dis.dis(lis[0])
3 0 LOAD_GLOBAL 0 (i)
3 RETURN_VALUE
In [26]: dis.dis(lis[1])
3 0 LOAD_GLOBAL 0 (i)
3 RETURN_VALUE
In [27]: dis.dis(lis[2])
3 0 LOAD_GLOBAL 0 (i)
3 RETURN_VALUE
Calling any of those functions returns the latest value of i
that is 2
in your sample code:
In [28]: lis[0]()
Out[28]: 2
if you delete i
object, you get an error:
In [29]: del i
In [30]: lis[0]()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-30-c9e334d64652> in <module>()
----> 1 lis[0]()
<ipython-input-18-15df6d11323a> in <lambda>()
1 lis = []
2 for i in range(3):
----> 3 lis.append( lambda: i )
NameError: global name 'i' is not defined
A solution could be to keep using the loop to write the code with the constants you need and actually run that code:
In [31]: lis = []
...: for i in range(3):
...: exec 'lis.append( lambda: {} )'.format(i)
...:
With the following results:
In [44]: lis[0]()
Out[44]: 0
In [45]: lis[1]()
Out[45]: 1
In [46]: dis.dis(lis[0])
1 0 LOAD_CONST 1 (0)
3 RETURN_VALUE
In [47]: dis.dis(lis[1])
1 0 LOAD_CONST 1 (1)
3 RETURN_VALUE