Частичное приложение прохладно. Что делает функциональность functools.partial
предложение, что Вы не можете пройти через лямбды?
>>> sum = lambda x, y : x + y
>>> sum(1, 2)
3
>>> incr = lambda y : sum(1, y)
>>> incr(2)
3
>>> def sum2(x, y):
return x + y
>>> incr2 = functools.partial(sum2, 1)
>>> incr2(4)
5
functools
так или иначе более эффективный, или читаемый?
Вот пример, который показывает разницу:
In [132]: sum = lambda x, y: x + y
In [133]: n = 5
In [134]: incr = lambda y: sum(n, y)
In [135]: incr2 = partial(sum, n)
In [136]: print incr(3), incr2(3)
8 8
In [137]: n = 9
In [138]: print incr(3), incr2(3)
12 8
Эти сообщения Ивана Мура расширяют «ограничения лямбда-выражения» и замыкания в python:
Какие функции functools.partial предложение, которое вы не можете пройти через лямбды?
Не так много с точки зрения дополнительных функциональных возможностей (но, см. ниже) - и удобочитаемость в глазах смотрящего.
Большинству людей, знакомых с функциональными языками программирования (в частности, из семейств Lisp / Scheme), похоже, очень нравится лямбда
- я говорю «большинство», определенно не все, потому что мы с Гвидо, несомненно, являемся одними из тех, кто "знаком с" (и т. д.), но думаем о лямбда
как о бредовой аномалии в Python ...
Он раскаивался в том, что когда-либо принимал его в Python, хотя планировал удалить его из Python 3, как один из «сбоев Python».
Я полностью его в этом поддержал. (Мне нравится лямбда
в схеме ... в то время как его ограничения в Python , и странный способ, которым он просто не вписывается в с остальными) языка, заставьте мою кожу ползать мурашками).
Однако не так для толпы любителей лямбда
, которые устроили один из самых близких к восстанию событий в истории Python, пока Гвидо не отступил и не решил оставить лямбда
дюймов
Несколько возможных дополнений к functools
(для создания функций, возвращающих константы, идентификационные данные и т. Д.) Не произошло (чтобы избежать явного дублирования большей части функций lambda
), хотя частично
, конечно, осталось (это не полная дупликация и не бельмо на глазу).
Помните, что тело лямбда
ограничено выражением , поэтому у него есть ограничения. Например ...:
>>> import functools
>>> f = functools.partial(int, base=2)
>>> f.args
()
>>> f.func
<type 'int'>
>>> f.keywords
{'base': 2}
>>>
Возвращенная функция functools.partial
украшена атрибутами, полезными для интроспекции - функцией, которую она оборачивает, и позиционными и именованными аргументами, которые она там исправляет. Кроме того, названные аргументы могут быть переопределены обратно («исправление» - это, скорее, в некотором смысле установка значений по умолчанию):
>>> f('23', base=10)
23
Итак, как вы видите, это определенно не такое упрощенное, как lambda s: int (s, base = 2)
! -)
Да, вы могли бы изменить свою лямбду, чтобы дать вам некоторые из них - например, для переопределения ключевого слова ,
>>> f = lambda s, **k: int(s, **dict({'base': 2}, **k))
но я очень надеюсь , что даже самый ярый лямбда
-любитель не сочтет этот ужас более понятным, чем частичное
] вызов!-). Часть «установки атрибута» еще сложнее из-за ограничения Python лямбда
«одним выражением тела» (плюс тот факт, что присваивание никогда не может быть частью выражения Python) ... вы в конечном итоге "подделка присваиваний в выражении" путем расширения понимания списка далеко за пределы его конструктивных ограничений ...:
>>> f = [f for f in (lambda f: int(s, base=2),)
if setattr(f, 'keywords', {'base': 2}) is None][0]
Теперь объедините возможность переопределения именованных аргументов плюс установку трех атрибутов в одно выражение и расскажите мне, насколько удобочитаемым , что будет ...! -)
Я быстрее всего понял замысел в третьем примере.
Когда я разбираю лямбды, я ожидаю большей сложности/однозначности, чем предлагает непосредственно стандартная библиотека.
Кроме того, вы заметите, что третий пример - единственный, который не зависит от полной сигнатуры sum2
; таким образом, он становится немного более свободно связанным.