4

So I don't really know how to explain this so bear with me.

Inside a for loop I have a lambda expression but I don't understand why you need the i=i part.

def makeActions():
    acts = []
    for i in range(5):
        acts.append(lambda x, i=i: x**i)
    return acts
smci
  • 32,567
  • 20
  • 113
  • 146
abctest
  • 153
  • 1
  • 1
  • 8
  • 3
    `lambda x, i=i: x**i` is equivalent to `lambda x, k=i: x**k`, which may make it less confusing. How are the elements of the `acts` list used later? – Arndt Jonasson Mar 27 '18 at 06:49
  • further to @ArndtJonasson comment, there `k` defines the second parameter of your `lambda`, and `=i` defines the default value. – Julien Mar 27 '18 at 06:51
  • The `i=i` idiom (traditionally called the "default value hack") is used to capture the current value of `i` from the outer scope, instead of capturing the variable `i`. Why? Well, if you capture the variable `i`, every time you call `acts[0](z)` or `acts[2](z)`, or any of the other functions, they'll all return `z**i` with the value of `i` at the time of the call—which means `z**4`. A default value, on the other hand, just copies the value at function creation time. So, `acts[0](z)` returns `z**0`, `acts[2](z)` returns `z**2`, etc. – abarnert Mar 27 '18 at 07:17
  • Renaming it to `k` as @ArndtJonasson did for the purposes of explaining what's happening is helpful. But in real-life code, the usual idiom is `i=i`, so you do have to get used to recognizing that too. – abarnert Mar 27 '18 at 07:18

1 Answers1

2

Let's break down your lambda function. It is a function that accepts two arguments (x, i) and execute x in the power of i.

The for loop CREATES new lambda function every iteration. If you remove the i=i, all the function would be the same: lambda x, i: x**i

So there is no mean to the for loop. They are all the same function.

Now the part i=i means assign the value of i from the for loop as a default argument for the function. The acts list would then have

[lambda x, i=1: x**i, lambda x, i=2: x**o, lambda ..]

Every iteration then creates a new lambda function, with a different value for i.


I think the part you get confused is both your for loop and the lambda uses the variable name i. However, the lambda defines a parameter (named i) and the for loop uses different variable with the same name. As @Arndt said in the comments, you can change the lambda definition to lambda x, y=i: x**y so it would be more clear.

Chen A.
  • 10,140
  • 3
  • 42
  • 61
  • 1
    This answer doesn't explain the key point. The comparison isn't to `lambda x, i: x**i`, it's to `lambda x: x**i`, using `i` as a closure variable. That looks like it should work at first glance, but doesn't. And the `i=i` idiom is specifically used to capture a variable by current value instead of by closure. – abarnert Mar 27 '18 at 07:13