Restrictons Python по сравнению с Ruby: лямбда

Я пробегался через некоторые страницы из WikiVS, из которого я заключаю в кавычки:

потому что лямбды в Python ограничиваются выражениями и не могут содержать операторы

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

Спасибо за Ваши ответы, комментарии и обратную связь!

6
задан Jordan Running 16 April 2010 в 16:15
поделиться

5 ответов

Я не думаю, что вы действительно спрашиваете о лямбдах, а о встроенных функциях .

Это действительно одно из серьезно раздражающих ограничений 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.

12
ответ дан 8 December 2019 в 03:38
поделиться

Наиболее часто встречающаяся ситуация с операторами - это, вероятно, оператор 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 .

9
ответ дан 8 December 2019 в 03:38
поделиться

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

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

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

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

1
ответ дан 8 December 2019 в 03:38
поделиться

Пример, который иногда приходил мне в голову, выглядит примерно так:

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 = ... ) является утверждением.

4
ответ дан 8 December 2019 в 03:38
поделиться

Вместо f = lambda s: pass вы можете использовать f = lambda s: None .

2
ответ дан 8 December 2019 в 03:38
поделиться