Re: can this be done without eval/exec?

2006-04-27 Thread Kent Johnson
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: can this be done without eval/exec?

2006-04-27 Thread Schüle Daniel
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
-- 
http://mail.python.org/mailman/listinfo/python-list


can this be done without eval/exec?

2006-04-26 Thread Schüle Daniel
Hello group,

  lst=[]
  for i in range(10):
... lst.append(eval(lambda:%i % i))
...
  lst[0]()
0
  lst[1]()
1
  lst[9]()
9
 

  lst=[]
  for i in range(10):
... exec tmp = lambda:%i % i  # assignment is not expression
... lst.append(tmp)
...
  lst[0]()
0
  lst[1]()
1
  lst[9]()
9
 

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

are there other solutions to this problem
without use of eval or exec?

Regards, Daniel
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: can this be done without eval/exec?

2006-04-26 Thread Chris Mellon
On 4/26/06, Schüle Daniel [EMAIL PROTECTED] wrote:
 Hello group,

   lst=[]
   for i in range(10):
 ... lst.append(eval(lambda:%i % i))
 ...
   lst[0]()
 0
   lst[1]()
 1
   lst[9]()
 9
  

   lst=[]
   for i in range(10):
 ... exec tmp = lambda:%i % i  # assignment is not expression
 ... lst.append(tmp)
 ...
   lst[0]()
 0
   lst[1]()
 1
   lst[9]()
 9
  

 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

 are there other solutions to this problem
 without use of eval or exec?


Using a factory function  closures instead of lambda:
 def maker(x):
... def inner_maker():
... return x
... return inner_maker
...
 lst = []
 for i in range(10):
... lst.append(maker(i))
...
 lst[0]()
0
 lst[5]()
5
 lst[9]()
9



 Regards, Daniel
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: can this be done without eval/exec?

2006-04-26 Thread Schüle Daniel
 are there other solutions to this problem
 without use of eval or exec?

 
 Using a factory function  closures instead of lambda:

  def a(x):
... def b():
... return x
... return b
...
  lst=[]
  for i in range(10):
... lst.append(a(i))
...
  lst[0]()
0
  lst[1]()
1
  lst[9]()
9
 

yes this works
I was playing a little more with this idea
and got into the next trouble :)

  cnt=0
  def a():
... def b():
... return cnt
... global cnt
... cnt += 1
... return b
...
  lst=[]
  for i in range(10):
... lst.append(a())
...
  lst[0]()
10
  lst[1]()
10
 

I figured out what was wrong, here is corrected version

  cnt = 0
  def a():
... global cnt
... tmp = cnt
... def b():
... return tmp
... cnt += 1
... return b
...
  lst=[]
  for i in range(10):
... lst.append(a())
...
  lst[0]()
0
  lst[1]()
1
 

Regards, Daniel
-- 
http://mail.python.org/mailman/listinfo/python-list