can this be done without eval/exec?
Kent Johnson
kent at kentsjohnson.com
Thu Apr 27 09:07:25 EDT 2006
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
More information about the Python-list
mailing list