?

Log in

No account? Create an account
Про lambda в python - Журнал Витуса.
[Друзья] [Свежие записи] [Dreamwidth] [Фото] [Тексты] [Друзья Ирины] [Матерные писатели] [Сообщества] [3 круг]
January 21st, 2010
09:14 pm
[User Picture]

[Link]

Previous Entry Share Next Entry
Про lambda в python
Вот в ru_python поставили задачу - имеется словарь. Выдать список строк вида
"ключ: значение", отсортированный порядке убывания значений.
Поскольку питон я знаю плохо, попробовал порешать.

Поскольку питон, опять таки знаю плохо, сначала придумал ответ на perl

map("$_: $x{$_}",sort($x{b}<=>$x{a},keys %hash));

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

Получилось:

[ x+" "+str(d[x]) for x in sorted( d.keys(), key=lambda(x): -d[x]]

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

[ x[0]+" "+str(x[1]) for x in sorted(d.items(), key=lambda(x): -x[1]]

НА сем и успокоился, и стал читать решения других читателей сообщества. Обнаружил что все как один испольуют вместо lambda импорт из модуля operator

from operator import getitem;

... key=getitem(1)


getitem описан как функция с двумя элементами. То есть тут еще и currying используется. Почему это для всех питонистов, соизволивших ответить на этот вопрос, сочетание импорта модуля, который фактически лезет куда-то в потроха интерпретатора, вроде перлового Opcode с currying кажется куда более естественным, чем старая добрая lambda?

Кто-то там собрался и провел бенчмарки, так мое решение с lambda, которое на мой взгляд, куда проще и естественней читается, оказалось вторым по скорости после решения avysk, которое вообще-то решением не является, а явялется только демонстрацией одного из шагов в решении (не тот порядок сортировки, нет преобразования tuple в строку через заданный разделитель)

Правда, у человека который предложил самое быстрое решение с getitem-ом испольузется кроме sorted еще и reversed, в то время как мне lambda позволяет просто поменять знак у ключей.

Господа питонисты, объясните откуда такая любовь к getitem-у берется.

Tags:

(82 comments)

Comments
 
[User Picture]
From:phd
Date:January 21st, 2010 06:31 pm (UTC)
(Link)
PEP 290, официальный документ: http://www.python.org/dev/peps/pep-0290/#replacing-common-uses-of-lambda

"The new functions run faster and are considered by some to improve readability."
(Replies frozen) (Thread)
[User Picture]
From:vitus_wagner
Date:January 21st, 2010 06:42 pm (UTC)
(Link)
Вот собственно о том я и спрашиваю: Почему эти функции "considered by some to improve readability"?

А насчет run faster - тут облом. Поскольку тут лямбда делает две вещи сразу, реализация, которая использует две функции из
PEP 290 - getitem и reversed оказывается медленнее, чем реализация, использущая ОДНУ лямбду. Видимо

lamda x: -x[1] - это uncommon use of lamda.

Странно что никому не пришло в голову использовать

sorted(d.items,key=getitem(1),reverse=True)

И что никто не пытался использовать оператор форматирования по шаблону для конструирования итоговой строки.
Побенчмаркать эти варианты что-ли.
(Replies frozen) (Parent) (Thread) (Expand)
(Deleted comment)
[User Picture]
From:vitus_wagner
Date:January 21st, 2010 06:44 pm (UTC)
(Link)
Причину этого выверта не надо изучать психологам. Она проста - этих студентов никогда не учили ни лямда-исчислению в курсе математики, ни Lisp-у в курсе программированя.
(Replies frozen) (Parent) (Thread) (Expand)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
[User Picture]
From:amarao_san
Date:January 21st, 2010 07:07 pm (UTC)
(Link)
не от django ли? Там в некоторых случаях, только им и обходишься. А ещё метаклассами.
(Replies frozen) (Thread)
[User Picture]
From:python_breeder
Date:January 21st, 2010 07:17 pm (UTC)
(Link)
Правильный ответ:


["%s: %s" % (key, value) for key, value in sorted(sdict.items(), key=lambda x: x[1], reverse=True)]

(Replies frozen) (Thread)
[User Picture]
From:vitus_wagner
Date:January 21st, 2010 07:19 pm (UTC)
(Link)
А-а-а, pattern matching!!! Это питон или erlang какой?!!
(Replies frozen) (Parent) (Thread) (Expand)
[User Picture]
From:dragsan
Date:January 21st, 2010 07:55 pm (UTC)
(Link)
Кажется тут небольшая путаница.

operator.getitem != operator.itemgetter
(Replies frozen) (Thread)
[User Picture]
From:gegmopo4
Date:January 21st, 2010 08:00 pm (UTC)
(Link)
Лямбда считается некошерной и её даже собирались убрать. Главная причина — убогость питоновской лямды. Жалеть не нужно, все случаи использования лямбды легко переписываются с использованием локальных именованных функций. Это и читабельнее, и мощнее.

Этот пример, например, можно решить таким способом.
def sortkey(x):
return x[1]
print ['%s %s' % x for x in sorted(d.items(), key = sortkey, reverse = True)]
(Replies frozen) (Thread)
From:pavla_dar
Date:January 21st, 2010 09:22 pm (UTC)

Ненавижу...

(Link)
Ненавижу именованные сущности, используемые не более, чем полтора раза.
Ненавижу, когда эран заполнен не алгоритмом, а флудом, дабы ублажить тупой компилятор и ограниченный язык.
Ненавижу С++/java за класс или обобщенный класс на каждый чих.
И люблю лямбы за их компактность, локальность, уместность и скромность.
(Replies frozen) (Parent) (Thread) (Expand)
[User Picture]
From:ramendik
Date:January 21st, 2010 09:17 pm (UTC)
(Link)
Вариант с lambda нечитаем для тех, кто не понимает этой концепции. Например, для меня.

(В питонной постановке задачи читабельность важнее скорости)
(Replies frozen) (Thread)
[User Picture]
From:arilou
Date:January 21st, 2010 10:49 pm (UTC)
(Link)
А что такого в той концепции? Ну кроме того, что надо залезть в руководство и прочитать, что означает слово 'lambda'?
(Replies frozen) (Parent) (Thread)
(Deleted comment)
(Deleted comment)
(Deleted comment)
[User Picture]
From:vitus_wagner
Date:January 22nd, 2010 06:56 am (UTC)
(Link)
Вот это я как раз и пытаюсь понять. Как использование функций из стандартной библиотеки вместо лямбды совместимо с философией "явное лучше неявного". По моему лямбда - это явное написание того что надо сделать. Вызов функции - ссылка на то, что где-то в другом месте написано что надо сделать (неявное).

Почему столько народу и в том, и в этом треде убеждены в обратном - я не понимаю.
(Replies frozen) (Parent) (Thread) (Expand)
(Deleted comment)
(Deleted comment)
[User Picture]
From:_winnie
Date:January 22nd, 2010 08:44 am (UTC)
(Link)
Забавно. Мне в C++ люто не хватало лямбд для STL-алгоритмов. Их эмуляция объектами-функциями или boost::bind была длинной и нечитабельной. Поэтому нелюбовь к ним очень странной кажется :)

Вариант с лямбдой мне тоже кажется более приятным - используется более универсальная кросс-языковая концепция, чем языко-специфичный import из operator, не дающий глобального знания. Студенту, знакомому с лямбдами, в этом случае не понадобится лезть в документацию.
(Replies frozen) (Thread)
[User Picture]
From:trueblacker
Date:January 22nd, 2010 08:56 pm (UTC)
(Link)
> Забавно. Мне в C++ люто не хватало лямбд для STL-алгоритмов. Их эмуляция объектами-функциями или boost::bind была длинной и нечитабельной. Поэтому нелюбовь к ним очень странной кажется :)

+100500
(Replies frozen) (Parent) (Thread)
From:nonstop [blogspot.com]
Date:January 22nd, 2010 09:03 am (UTC)

хмм

(Link)
Я поковырявшись придумал вот такое:
["{0} {1}".format(x, y) for x, y in sorted(lst.items(), cmp = lambda x, y: -cmp(x[1], y[1]))]

Вроде бы нагляднее некуда: генератор + сортировка.
Потом поглядел на ваше - очень похоже.
(Replies frozen) (Thread)
[User Picture]
From:potan
Date:January 22nd, 2010 11:10 am (UTC)

Re: хмм

(Link)
-cmp(x[1], y[1]) не то же самое, что cmp(y[1], x[1])?
(Replies frozen) (Parent) (Thread) (Expand)
My Website Powered by LiveJournal.com