0

I am reading about lambda expressions at https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions, and I do not understand where sort() gets its parameters from here. It shows:

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

where "pair: pair[1]" was not named before being used in lambda. I also did:

In [23]: pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

In [24]: pairs.sort(key=lambda x: x[1])

In [25]: pairs
Out[25]: [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

In [26]: pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

In [27]: pairs.sort(key=lambda randomname: randomname[1])

In [28]: pairs
Out[28]: [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

In [29]: pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

In [30]: pairs.sort(key=lambda randomname: mismatch[1])
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
...
NameError: global name 'mismatch' is not defined

This shows me that the lambda can take any random parameter name, and knows to get the [1] spot from the pairs list.

I also do not understand what "key" is even taking, as the docs say it takes a function of one argument, then use key=str.lower as an example. But using their exact example fails:

student_tuples
Out[55]: [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ('John', 'b', 5)]


In [60]: sorted(student_tuples, key=str.lower)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-60-86a57d272cfb> in <module>()
----> 1 sorted(student_tuples, key=str.lower)

TypeError: descriptor 'lower' requires a 'str' object but received a 'tuple'


In [61]: sorted(student_tuples, key=str.lower())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-61-983b5ca19cdb> in <module>()
----> 1 sorted(student_tuples, key=str.lower())

TypeError: descriptor 'lower' of 'str' object needs an argument

Even when giving it strings as an iterable, the str.lower method fails:

In [68]: strings
Out[68]: ['str', 'str2', 'str3']

In [69]: sorted(strings, str.lower)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-69-271d28a2618f> in <module>()
----> 1 sorted(strings, str.lower)

TypeError: lower() takes no arguments (1 given)

My question is

  1. how did the lambda function know to assign the position in the current iterable (calling the iterable itself gets TypeErro:'tuple' object is not callable)

  2. What is key actually taking, and does it only take lambdas?

Thank you

codyc4321
  • 9,014
  • 22
  • 92
  • 165
  • `key` takes the whole item and passes it to the function, now whatever that function returns is used for the comparison. – Ashwini Chaudhary Jul 06 '15 at 20:48
  • 1
    The argument is a function. `lambda x : x[1]` defines a function with a parameter `x` that returns `x[1]`. – khelwood Jul 06 '15 at 20:49
  • I wonder why key didn't accept `str.lower`, which is also a function right? `In [65]: str.lower Out[65]: ` – codyc4321 Jul 06 '15 at 20:51
  • 3
    @codyc4321: Because `str.lower` only works on strings, not on tuples. – Kevin Jul 06 '15 at 20:51
  • Sorry, but this isn't duplicate, where can anyone site someone using the failure of str.lower as an example in understanding the sort function? – codyc4321 Jul 06 '15 at 20:55
  • 1
    I agree that it's not a duplicate. But the answers in the "duplicate" are worth reading, and might help you understand how this works. `key` can be any function, and doesn't have to be a lambda. Lambda is just syntactic sugar in python. You could pass it a function defined like this `def keyfunction(pair): return pair[1]` instead. Like this `sorted(pairs, key=keyfunction)` – Håken Lid Jul 06 '15 at 21:04
  • 1
    In your last example, you forgot to use `key=`. If you replace it with `sorted(strings, key=str.lower)`, it works – happydave Jul 06 '15 at 21:06
  • 1
    `str.lower` didn't fail; you simply didn't give it strings. It only works on strings. It can't lowercase tuples any more than you can take the square root of someone's name. – TigerhawkT3 Jul 06 '15 at 23:15
  • is there a way to report mods for abusing the system? – codyc4321 Jul 07 '15 at 02:41
  • in line 68-69, I gave it a list of strings – codyc4321 Jul 07 '15 at 12:43
  • @codyc4321: You could go ask on [meta], but I'd take a more conciliatory tone if I were you. "Why was my question closed?" rather than "Why is this mod a jerk?" Also, your question was not closed by a mod in the first place. – Kevin Jul 07 '15 at 15:26
  • As for 68-69, my psychic powers tell me you have a variable named `str`. Don't do that. It breaks things. – Kevin Jul 07 '15 at 15:28
  • that's good advice, although if they did not compare the 2 questions to each other, it still seems abusing their privilege to me. – codyc4321 Jul 07 '15 at 16:43
  • line 68-69 is at the bottom of the question, and shows 'strings' which is a list of strings – codyc4321 Jul 07 '15 at 17:32

0 Answers0