Если логика слишком сложна для выражения генератора, вам, вероятно, не следует использовать лямбду. Это не то же самое, что сказать, что ты не можешь.
В Python-лямбдах может быть столько символов новой строки, сколько вы хотите. Они просто не могут содержать операторов , только выражения. Вы можете использовать yield
выражение (не yield
выражение - вам нужны дополнительные скобки) в лямбде.
>>> list((lambda: (yield 1))())
[1]
Не так ли полезно, не так ли? Вы можете выполнить список выражений доходности, используя ... выражение отображения списка - []
. (Python гарантирует, что элементы дисплеев будут оцениваться по порядку.)
>>> tuple((lambda:[
(yield 1),
(yield 2),
(yield 3),
])())
(1, 2, 3)
Кортежи тоже работают. Посмотри на это. Несколько «строк» (не операторов). Все еще не так полезно. Вы хотите иметь возможность зацикливаться. Но утверждение for
- это утверждение. (Опять же, почему бы не использовать выражение-генератор? Эти являются выражениями.) На практике это не такое ограничение, поскольку лямбда-выражения могут вызывать функции, содержащие операторы.
>>> def loop(itr, body):
for x in itr:
yield body(x)
>>> list(loop(range(9), lambda x: x*x))
[0, 1, 4, 9, 16, 25, 36, 49, 64]
Вот как сделать цикл for выражением без использования понимания. Но мы хотим петлю внутри лямбды.
>>> list((lambda:
(yield from loop(range(9), lambda x:
x*x))
)())
[0, 1, 4, 9, 16, 25, 36, 49, 64]
Да, yield from
также является выражением. Если вы заключите его в скобки. Я думаю, что хорошо выделенные def
легче читать, хотя. Вы можете дать ему короткое одноразовое имя, например _f
или что-то еще.
Лямбда-исчисление является самостоятельным по Тьюрингу, способным вычислять все, что можно вычислить.
Это означает, что технически нам даже не нужна функция loop
. Вместо этого вы можете использовать рекурсию. (Несмотря на то, что в Python вы в конечном итоге получите переполнение стека.) Но как вы можете использовать анонимную функцию?
Вы используете «декоратор», чтобы дать ему имя.
>>> def recur(func):
def wrapper(*args, **kwargs):
return func(func, *args, **kwargs)
return wrapper
>>> tuple(recur(lambda r, n:[
(yield n),
(yield from r(r, n-1)) if n else 0]
)(3))
(3, 2, 1, 0)
Конечно, «декоратор» тоже может быть анонимным.
>>> tuple((lambda f: lambda *a, **kw: f(f, *a, **kw))(lambda r, n:[
(yield n),
(yield from r(r, n-1)) if n else 0]
)(3))
(3, 2, 1, 0)
Во-первых, я не писал это так, потому что ваши глаза застеклились бы, увидев слишком много лямбд. Вот почему вы должны использовать def
!
Если вас интересует, как далеко мы можем толкать лямбды, как это, посмотрите Drython , в котором есть аналогичные замены выражений для каждого оператора Python.