Синтаксис после сортировки (ключ = лямбда: ...) - PullRequest
130 голосов
/ 23 января 2012

Я не совсем понимаю синтаксис аргумента sorted():

key=lambda variable: variable[0]

Не является ли lambda произвольным? Почему variable указано дважды в том, что выглядит как dict?

Ответы [ 6 ]

140 голосов
/ 23 января 2012

key - это функция, которая будет вызываться для преобразования элементов коллекции перед их сравнением. Параметр, передаваемый в key, должен быть вызванным.

Использование lambda создает анонимную функцию (которая вызывается). В случае sorted вызываемый объект принимает только один параметр. Python lambda довольно прост. Он может только сделать и вернуть одну вещь.

Синтаксис lambda - это слово lambda, за которым следует список имен параметров, а затем отдельный блок кода. Список параметров и блок кода обозначаются двоеточием. Это похоже на другие конструкции в python, такие как while, for, if и так далее. Все эти операторы, как правило, имеют блок кода. Лямбда - это просто еще один экземпляр оператора с блоком кода.

Мы можем сравнить использование лямбды с использованием def для создания функции.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

Лямбда просто дает нам способ сделать это без присвоения имени. Что делает его отличным для использования в качестве параметра функции.

variable используется здесь дважды, потому что слева от двоеточия это имя параметра, а справа оно используется в блоке кода для вычисления чего-либо.

107 голосов
/ 23 марта 2017

Я думаю, что все ответы здесь охватывают суть того, что лямбда-функция делает в контексте sorted () довольно хорошо, однако я все еще чувствую, что описание, которое приводит к интуитивному пониманию, отсутствует, поэтому вот мои двацентов.

Ради полноты излагаю очевидное заранее: sorted () возвращает список отсортированных элементов, и если мы хотим отсортировать определенным образом или если мы хотим отсортировать сложный списокэлементы (например, вложенные списки или список кортежей) мы можем вызвать ключевой аргумент.

Для меня интуитивное понимание ключевого аргумента, почему он должен вызываться, и использование лямбды в качестве (анонимная) вызываемая функция для достижения этой цели состоит из двух частей.

  1. Использование lamba в конечном итоге означает, что вам не нужно писать (определять) целую функцию, как та, что sblom предоставил пример.Лямбда-функции создаются, используются и немедленно уничтожаются, поэтому они не наполняют ваш код большим количеством кода, который будет использоваться только один раз.Это, насколько я понимаю, основная утилита лямбда-функции, и ее приложения для таких ролей широки.Его синтаксис является чисто условным, что по сути является природой программного синтаксиса в целом.Изучите синтаксис и покончите с этим.

Синтаксис лямбды следующий:

лямбда input_variable (s) : один вкусный лайнер

например

In [1]: f00 = lambda x: x/2

In [2]: f00(10)
Out[2]: 5.0

In [3]: (lambda x: x/2)(10)
Out[3]: 5.0

In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0

In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
Идея аргумента key заключается в том, что он должен принимать набор инструкций, которые по существу будут указывать функцию sorted () на те элементы списка, которые должны использоваться для сортировки.Когда он говорит key=, то на самом деле это означает: когда я перебираю список по одному элементу за раз (т.е. для e в списке), я собираюсь передать текущий элемент функции, которую я предоставляю в аргументе ключа.и использовать это, чтобы создать преобразованный список, который сообщит мне о порядке окончательного отсортированного списка.

Проверьте это:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)

Базовый пример:

sorted(mylist)

[2, 3, 3, 4, 6, 8,23] # все числа в порядке от малого к большому.

Пример 1:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)

[3, 3, 23, 6, 2, 4,8] # Имеет ли этот отсортированный результат интуитивный смысл для вас?

Заметьте, что моя лямбда-функция сказала сортировать, чтобы проверить, была ли (e) четной или нечетной перед сортировкой.

НО ЖДУ!Вы можете (или, возможно, должны) задаться вопросом о двух вещах - во-первых, почему мои шансы наступают раньше, чем мои события (поскольку мое значение ключа, похоже, говорит моей отсортированной функции назначать приоритеты для событий с помощью оператора mod в x%2==0).Во-вторых, почему мои вечера вышли из строя?2 предшествует 6 верно?Анализируя этот результат, мы узнаем кое-что более глубокое о том, как работает аргумент «key» sorted (), особенно в сочетании с анонимной лямбда-функцией.

Во-первых, вы заметите, что, хотя шансы наступают раньше вечера, сами вечера не сортируются.Почему это?? Давайте прочитаем документы :

Функции клавиш Начиная с Python 2.4, в list.sort () и sorted () добавлен ключевой параметр для указанияфункция, вызываемая для каждого элемента списка перед сравнением.

Мы должны немного прочитать между строк здесь, но это говорит нам о том, что функция сортировки вызывается только один раз, и если мы указываем ключевой аргумент, то мы сортируем по значению, на которое указывает нам ключевая функция.

Так что же возвращает пример с модулем?Логическое значение: True == 1, False == 0.Так как же сортировка справляется с этим ключом?Он в основном преобразует исходный список в последовательность 1 и 0.

[3,6,3,2,4,8,23] становится [0,1,0,1,1,1,0]

Теперь мы кое-что получаем.Что вы получаете, когда сортируете преобразованный список?

[0,0,0,1,1,1,1]

Хорошо, теперь мы знаем, почему шансы наступают раньше вечера.Но следующий вопрос: почему 6 все еще стоят перед 2 в моем окончательном списке?Ну, это легко - это потому, что сортировка происходит только один раз!т.е. те 1 все еще представляют исходные значения списка, которые находятся в их исходных положениях относительно друг друга.Поскольку сортировка происходит только один раз, и мы не вызываем какую-либо функцию сортировки для упорядочения исходных четных значений от низкого к высокому, эти значения остаются в своем первоначальном порядке относительно друг друга.

Последний вопрос:тогда это: как я концептуально думаю о том, как порядок моих логических значений преобразуется обратно в исходные значения, когда я распечатываю окончательный отсортированный список?

Sorted () - это встроенный метод, который (забавный факт) использует гибридный алгоритм сортировки под названием Timsort , который объединяет аспекты сортировки слиянием и сортировки вставкой.Мне кажется ясным, что когда вы вызываете его, есть механизм, который хранит эти значения в памяти и связывает их с их логическим тождеством (маской), определяемым (...!) Лямбда-функцией.Порядок определяется их булевой идентичностью, рассчитанной по лямбда-функции, но имейте в виду, что эти подсписки (единиц и нулей) сами по себе не сортируются по их исходным значениям.Следовательно, окончательный список, хотя и организован по коэффициентам и событиям, не отсортирован по подспискам (в этом случае четные номера не соответствуют порядку).Тот факт, что шансы упорядочены, объясняется тем, что они уже были в порядке по совпадению в исходном списке.Вывод из всего этого заключается в том, что когда лямбда выполняет это преобразование, первоначальный порядок подсписков сохраняется.

Так как же все это связано с исходным вопросом и, что более важно, с нашей интуицией о том, как мы должны реализовать sorted () с ее ключевым аргументом и лямбда-выражением?

Эта лямбда-функция может бытьрассматривается как указатель, который указывает на значения, по которым мы должны отсортировать, является ли указатель отображением значения в его логическое значение, преобразованное лямбда-функцией, или если это конкретный элемент во вложенном списке, кортеже, dict и т. д.,снова определяется лямбда-функцией.

Давайте попробуем предсказать, что произойдет, когда я запущу следующий код:

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

Мой sorted вызов явно говорит: "Пожалуйста, сортируйте этот список".Ключевой аргумент делает это немного более конкретным, говоря, что для каждого элемента (x) в mylist возвращают индекс 1 этого элемента, а затем сортируют все элементы исходного списка 'mylist' по отсортированномупорядок списка, вычисляемый лямбда-функцией.Поскольку у нас есть список кортежей, мы можем вернуть индексированный элемент из этого кортежа.Таким образом, мы получаем:

[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]

Запустите этот код, и вы увидите, что это заказ.Попробуйте проиндексировать список целых чисел, и вы обнаружите, что код ломается.

Это было длинное объяснение, но я надеюсь, что это поможет «разобраться» в вашей интуиции об использовании лямбда-функций в качестве ключевого аргумента.в отсортированном виде () и далее.

25 голосов
/ 23 января 2012

lambda - ключевое слово Python, которое используется для генерации анонимных функций .

>>> (lambda x: x+2)(3)
5
12 голосов
/ 23 января 2012

variable слева от : является именем параметра.Параметр variable справа использует параметр.

Значит почти так же, как:

def some_method(variable):
  return variable[0]
3 голосов
/ 23 января 2012

lambda - анонимная функция, а не произвольная функция.Принимаемым параметром будет переменная, с которой вы работаете, и столбец, по которому вы его сортируете.

2 голосов
/ 25 октября 2013

Поскольку использование лямбды было задано в контексте sorted(), взгляните и на это https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

...