Я пробегался через некоторые страницы из WikiVS, из которого я заключаю в кавычки:
потому что лямбды в Python ограничиваются выражениями и не могут содержать операторы
Я хотел бы знать то, что будет хорошим примером (или больше), где это ограничение было бы, предпочтительно по сравнению с языком Ruby.
Спасибо за Ваши ответы, комментарии и обратную связь!
Я не думаю, что вы действительно спрашиваете о лямбдах, а о встроенных функциях .
Это действительно одно из серьезно раздражающих ограничений Python: вы не можете определить функцию (настоящую функцию, а не просто выражение) встроенной; вы должны дать ему имя. Это очень расстраивает, так как любой другой современный язык сценариев делает это, и часто бывает очень болезненно перемещать функции вне очереди. Это также расстраивает, потому что я чувствую, что байт-код Python может представлять это тривиально - это просто синтаксис языка, который не может.
Javascript:
responses = {
"resp1": {
"start": function() { ... },
"stop": function() { ... },
},
"resp2": {
"start": function() { ... },
"stop": function() { ... },
},
...
}
responses["resp1"]["start"]();
Lua:
responses = {
resp1 = {
start = function() ... end;
end = function() ... end;
};
...
}
responses.resp1.start();
Ruby:
responses = {
"resp1" => {
"start" => lambda { },
"stop" => lambda { },
},
}
responses["resp1"]["start"].call
Python:
def resp1_start():
pass
def resp1_stop():
pass
responses = {
"resp1": {
"start": resp1_start,
"stop": resp1_stop,
},
}
responses["resp1"]["start"]()
Обратите внимание, что в JavaScript и Lua нет лямбда-выражений: у них нет причин для существования, поскольку встроенные функции покрывают их гораздо более естественным и общим способом.
Я бы, наверное, оценил это как самое раздражающее повседневное ограничение Python.
Наиболее часто встречающаяся ситуация с операторами - это, вероятно, оператор Python 2.X print
.
Например,
say_hi = lambda name: "Hello " + name
работает должным образом.
Но это не скомпилируется:
say_hi = lambda name: print "Hello " + name
потому что print
не является правильной функцией в Python 2.
>>> say_hi = lambda name: "Hello " + name
>>> say_hi("Mark")
'Hello Mark'
>>>
>>> say_hi = lambda name: print "Hello " + name
SyntaxError: invalid syntax
Остальные операторы, кроме print
, можно найти в документации Python в Интернете :
simple_stmt :: = expression_stmt | assert_stmt | assignment_stmt | augmented_assignment_stmt | pass_stmt | del_stmt | print_stmt | return_stmt | yield_stmt | Raise_stmt | break_stmt | continue_stmt | import_stmt | global_stmt | exec_stmt
Вы можете попробовать остальные из них в REPL, если хотите, чтобы они терпели неудачу:
>> assert(True)
>>> assert_lambda = lambda: assert(True)
SyntaxError: invalid syntax
>>> pass
>>> pass_lambda = lambda: pass
SyntaxError: invalid syntax
Я не уверен, какие параллели существуют между ограничениями Python лямбда
и proc
или лямбда
Ruby. В Ruby все является сообщением, поэтому у вас нет ключевых слов (хорошо, у вас есть ключевые слова , но у вас нет ключевых слов, которые выглядят как функции вроде Python print
). Вне всяких сомнений, не существует легко ошибочных конструкций Ruby, которые потерпят неудачу в proc
.
лямбда
- это просто ярлык в Python для определения функции, возвращающей простое выражение.
Это не является значимым ограничением. Если вам нужно более одного выражения, просто используйте функцию: нет ничего , которое вы можете сделать с лямбда-выражением, чего нельзя сделать с функцией.
Единственным недостатком использования функции вместо лямбда является то, что функция должна быть определена в 1 или нескольких отдельных строках (так что вы можете потерять некоторую локальность по сравнению с лямбда), и вам нужно придумать имя для функция (но если вы не можете придумать одну, тогда f
обычно работает).
Все другие причины, по которым люди думают, что им нужно использовать лямбда (например, доступ к вложенным переменным или создание большого количества лямбда-выражений с отдельными аргументами по умолчанию), будут работать так же хорошо с функцией.
Большим преимуществом использования именованной функции, конечно же, является то, что когда что-то идет не так, вы получаете значимую трассировку стека. Я был так укусил меня вчера, когда я получил трассировку стека, включающую лямбду, и не было контекста о том, какая это была лямбда.
Пример, который иногда приходил мне в голову, выглядит примерно так:
def convert(value):
n = expensive_op(value)
return (n, n + 1)
new_list = map(convert, old_list)
Несмотря на то, что он достаточно короткий и приятный, вы не можете преобразовать его в лямбду без необходимости запустите own_op ()
дважды (что, как следует из названия, вы не хотите), то есть вам придется выполнить
new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list)
, потому что присвоение ( n = ...
) является утверждением.
Вместо f = lambda s: pass
вы можете использовать f = lambda s: None
.