1

I cannot find out what key=key does in this simple python code:

for key in dict:
    f = (lambda key=key: print(key))
    print(f())
martineau
  • 119,623
  • 25
  • 170
  • 301
Tom Becker
  • 191
  • 1
  • 1
  • 5
  • You are passing the `key` iterator to your lambda function. Actually, you could have even had it as `lambda foo=key: print(foo)` just to make it a bit more clear of what is exactly going on. Also, because you have a lambda that pretty much prints your `key`, that `print(f())` is redundant and will print `None`. So, you just need to call `f()`. But, this is a very odd design choice for printing a key. Why not just simply `print(key)` – idjaw Oct 15 '16 at 15:53
  • .why assigned key back to key? "key=key"....who wrote that?.....could be the coder was tired...lol – repzero Oct 15 '16 at 15:54
  • @repzero It's not assigning key back to key. The lambda takes a single argument, and that argument was named `key`. The name actually has nothing to do with the actual iterator `key`. As I explained in my comment, it would have been `foo=key`. – idjaw Oct 15 '16 at 15:56
  • @idjaw..point noted...I haven't used lambda function for nothing really..but it seemed a little awkward when I see this..... – repzero Oct 15 '16 at 15:58
  • 1
    @repzero It is in fact a very strange piece of code. – idjaw Oct 15 '16 at 15:59

2 Answers2

3

In this piece of code, key=key does nothing useful at all. You can just as well write the loop as

for key in [1,2,3]:
    f = lambda: key
    print(f())

This will print 1, 2, and 3. (Note that -- unrelated to the problem -- I also removed the print from the lambda, instead returning the value directly, because it's redundant and will only make the "outer" print print None, as that's what the function would return with print.)

But what if you do not execute the function right within the loop, but afterwards?

functions = []
for key in [1,2,3]:
    f = lambda: key
    functions.append(f)

for f in functions:
    print(f())

Now, this will print 3, 3, and 3, as the key variable is evaluated when the function is called, not when it is defined, i.e. after the loop when it has the value 3. This can lead to some serious surprises e.g. when defining callback functions for different buttons in a loop.

Here, using key=key comes into play: This will create a parameter key and assign to it the current value of the key variable in the loop when the function is defined as a default value (hence you do not have to pass a parameter when calling the function). The value of that key paremeter will then stay the same within the scope of the function when the function is called later:

functions = []
for key in [1,2,3]:
    f = lambda key=key: key
    functions.append(f)

This prints 1, 2, and 3, as would be expected. As others have noted, you can use a different name for the parameter, to make this less confusing, e.g. f = lambda param=key: param.

Community
  • 1
  • 1
tobias_k
  • 81,265
  • 12
  • 120
  • 179
2

This code is not "simple", it's actually somewhat tricky to understand for a Python novice.

The for key in dict: simply loops over what dict is. Normally dict is a predefined system library class (the class of standard dictionaries) and iterating over a class object is (normally) nonsense.

Python however allows to redefine what dict is bound to: dict is not a keyword, but just a regular name that can be reused as you like - if you like to write bad python code that confuses IDEs and fellow programmers.

I'll assume that dict in this context is some kind of container that can be iterated over: it could be a list, a tuple or a dictionary (as the name suggests) for example. Note that iterating over a dictionary means in Python iterating over dictionary keys.

f = (lambda key=key: print(key))

this code creates an unnamed function that accepts a parameter named key, and defines the default value to be current value of variable key used in the loop. The body of the function simply calls the standard print function passing key as argument.

The code is equivalent to:

f = lambda x=key: print(x)

that is probably a bit clearer for a novice because avoids reusing the same name.

Finally at each iteration this function is called passing no parameters and the result is sent to print standard function. The evaluation of f() will print the key value (passing no parameters the default value will be used) and the result of print (that is None) will be printed by the second print call.

There is really nothing good about this example. Actually the lambda x=x:... is a pattern in Python and sometimes is necessary but here is complete nonsense and there's nothing to learn from this use.

You should reconsider continuing reading from the source you got this from (I'd suspect that the rest is bad stuff also). Stick to official tutorials for better examples...

6502
  • 112,025
  • 15
  • 165
  • 265