lambda

Ben C spamspam at spam.eggs
Fri Apr 21 19:05:47 EDT 2006


On 2006-04-21, Alexis Roda <arv.nntp at gmail.com> wrote:
> Ben C escribió:
>> On 2006-04-21, Ben C <spamspam at spam.eggs> wrote:
>> Having said that, I attempted to confirm this using def rather than
>> lambda, and encountered something I cannot explain at all-- it appears
>> that the functions are getting redefined whenever they are called, to
>> effect a kind of "dynamic scoping" behaviour. I would appreciate any
>> explanation anyone can give of this:
>> 
>> fns = []
>> for y in range(2):
>>  def fn():
>>      yy = y      # exactly the same with yy = int(y)
>>      print "defining fn that returns", yy
>>      return yy
>>  print "Appending at", y
>>  print fn, fn()
>>  fns.append(fn)
>
>
> yy = y does assign y's current value (current == fn call time, not fn 
> definition time). To return 0 and 1 as expected you should create a 
> "different/private" y for every fn's definition.
>
> ----------------------------------------
>
> fns = []
> for y in range(2):
>   def fn(y=y):
>       yy = y
>       print "defining fn that returns", yy
>       return yy
>   print "Appending at", y
>   print fn, fn()
>   fns.append(fn)
>
>
> ----------------------------------------

Yes; the difficulty is that the body of the function is executed
(obviously) every time you call it. The body of the function reads y
which is a global variable and has whatever value it has at the time.

The parameters are the only part of a function definition where you get
to write some code that initializes things in the function's "frame"
when the function is defined rather than when it's called.

I got confused because I was thinking of yy = y in the body of fn's
definition as an initialization, not as an assignment. In other
languages it's possible to distinguish, but not in Python.

Really this is what classes are for in Python:

def f(x):
    return x * x

class fn(object):
    def __init__(self, y):
        # "define-time" things are here
        self.y = y

    def __call__(self, x):
        # "call-time" things are here
        return f(x) * self.y

fns = [fn(i) for i in range(1, 10)]
for f in fns:
    print f(1)

is I think quite a good way to do this.



More information about the Python-list mailing list