4

Here is the example python code.

f_list = [lambda x : x ** i for i in range(5)]
[f_list[j](10) for j in range(5)]

I thought the output would be:

[1, 10, 100, 1000, 10000]

But I got this instead:

[10000, 10000, 10000, 10000, 10000]

I'm wondering what actually happened when I run this code. And what's the connections with lazy evaluation.

  • 1
    There's definite a duplicate for this somewhere. In short, your functions are not closures over `i`; each function in `f_list` is the *exact* same function whose body references a global variable `i`, whose value is looked up when the function is *called*. – chepner Oct 31 '18 at 15:13
  • 1
    The result is [10000, 10000, 10000, 10000, 10000] – Andreas K. Oct 31 '18 at 15:22
  • Yes, because each and every function in the list sees `i == 4` when it gets called, as that's the last value assigned to `i` by the list comprehension. The value of `i` at the time the `lambda` expression is evaluated to produce the function is irrelevant. – chepner Oct 31 '18 at 15:29
  • For Python 3 (to correct my original comment), `i` is not a global variable, but a non-local variable specific to the list comprehension but shared by all the functions – chepner Oct 31 '18 at 15:30
  • @AndyK I just forgot the “0” –  Nov 01 '18 at 00:21
  • @chepner Thx! Your answer is really helpful. –  Nov 01 '18 at 04:51
  • 2
    Personally, I prefer this `f_list = [lambda x, j=i : x ** j for i in range(5)]` and `[f_list[j](10) for j in range(5)]` gives `[1, 10, 100, 1000, 10000]`. – GZ92 May 08 '22 at 16:49

1 Answers1

2

Here is a good example of why curryfying is good, you can achieve your goal currying your function like this:

f_list = [(lambda y : lambda x : x ** y)(i) for i in range(5)]
r = [f_list[j](10) for j in range(5)]

The result will be:

=> [1, 10, 100, 1000, 10000]

Currying:

The simple way to understand what curry is for me is the next one, instead of give to a function all the parameters it needs, you create a function, that always receives one parameter, and returns another function that takes again one parameter, and in the final function, you do the transformation you need with all the parameters

A little example:

sum_curry = lambda x : lambda y : x + y

here you've got a simple sum function, but imagine you want to have the function plus_one, ok, yuu can reuse the function above like this:

plus_one = sum_curry(1)
developer_hatch
  • 15,898
  • 3
  • 42
  • 75