can this be done without eval/exec?

Schüle Daniel uval at rz.uni-karlsruhe.de
Thu Apr 27 16:14:15 EDT 2006


Kent Johnson schrieb:
> Schüle Daniel wrote:
>> and now the obvious one (as I thought at first)
>>
>>  >>> lst=[]
>>  >>> for i in range(10):
>> ...     lst.append(lambda:i)
>> ...
>>  >>> lst[0]()
>> 9
>>  >>> i
>> 9
>>  >>>
>>
>> I think I understand where the problem comes from
>> lambda:i seems not to be fully evalutated
>> it just binds object with name i and not the value of i
>> thus lst[0]() is not 0
> 
> The problem is that variables in closures are not bound until the 
> variable goes out of scope. So each lambda is bound to the final value 
> of i.
>>
>> are there other solutions to this problem
>> without use of eval or exec?
> 
> The workaround is to use a default argument to bind the current value of i:
> In [1]: lst = []
> 
> In [2]: for i in range(10):
>    ...:     lst.append(lambda i=i: i)
>    ...:
>    ...:
> 
> In [3]: lst[0]()
> Out[3]: 0
> 
> In [4]: lst[5]()
> Out[4]: 5
> 
> A list comp makes this IMO cleaner:
> In [5]: lst = [ lambda i=i: i for i in range(10) ]
> 
> In [6]: lst[0]()
> Out[6]: 0
> 
> In [7]: lst[5]()
> Out[7]: 5
> 
> Kent

many thanks for the explaination,
it look much simpler than my solutions too

Daniel



More information about the Python-list mailing list