Как работает ключевой аргумент для сортировки?
Код 1:
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
Код 2:
>>> student_tuples = [
... ('john', 'A', 15),
... ('jane', 'B', 12),
... ('dave', 'B', 10),
... ]
>>> from operator import itemgetter, attrgetter
>>>
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
Почему в коде 1 есть ()
опущен в key=str.lower
, и он сообщает об ошибке, если скобки включены, но в коде 2 в key=itemgetter(2)
скобки сохранены?
2 ответа
key
аргумент sorted
ожидает функцию, которая sorted
затем применяется к каждому элементу сортируемой вещи. Результат key(item)
сравниваются друг с другом, а не каждый оригинал item
, в процессе сортировки.
Вы можете представить, что это работает примерно так:
def sorted(thing_to_sort, key):
#
# ... lots of complicated stuff ...
#
if key(x) < key(y):
# do something
else:
# do something else
#
# ... lots more complicated stuff ...
#
return result
Как видите, скобки ()
добавлены в функцию key
внутри sorted
, применяя его к x
а также y
, которые являются предметами thing_to_sort
,
В вашем первом примере str.lower
это функция, которая применяется к каждому x
а также y
,
itemgetter
немного отличается Это функция, которая возвращает другую функцию, и в вашем примере это та другая функция, которая применяется к x
а также y
,
Вы можете увидеть, как itemgetter
работает в консоли:
>>> from operator import itemgetter
>>> item = ('john', 'A', 15)
>>> func = itemgetter(2)
>>> func(item)
15
Поначалу может быть немного сложно разобраться с функциями "высшего порядка" (которые принимают или возвращают другие функции), но они очень полезны для множества различных задач, поэтому стоит поэкспериментировать с ними, пока вы не почувствуете себя комфортно,
Ковыряюсь с консолью немногоstr.lower
переходит к методу 'lower' из 'str' объектов и str.lower()
это функция, как никогда str.lower()
требует аргумента, поэтому правильно написано было бы str.lower("OH BOY")
и он вернется oh boy
ошибка в том, что вы не передали аргументы функции, но она ожидала.