Python: lambda, yield-statement/expression и loop (Clarify)
TLDR:
Можем ли мы реализовать yield
или инструкцию генератора (с циклом) в пределах lambda
?
Мой вопрос заключается в том, чтобы уточнить:
Можно ли реализовать следующую простую функцию цикла с выходом
def loopyield():
for x in range(0,15):
yield x
print(*loopyield())
Результаты с ошибкой:
lamyield=lambda x: yield x for x in range(0,15)
^
SyntaxError: invalid syntax
Похоже, он ожидал чего-то в качестве правильного операнда для неписаного оператора возврата, но нашел yeild
и запутался.
Есть ли законный способ достичь этого в цикле?
Боковое примечание: yield
может быть выражением/выражением в зависимости от того, кого вы спрашиваете: yield - statement или expression?
Конечный ответ: доход может использоваться с лямбдой, но ограничение (однострочное) делает его бесполезным. for/while
невозможно в лямбда, потому что они не являются выражениями. -user2357112 неявный для цикла возможен с пониманием списка, и доходность действительна в понимании списка. -wim
Вердикт - Явные петли невозможны, потому что lambdas в python может содержать только выражения, а для записи явного цикла вам понадобятся операторы. -wim
Ответы
Ответ 1
Единственная строка, которую вы пытаетесь создать, технически возможна с помощью лямбды, вам просто нужно помочь парсеру немного больше:
>>> lamyield = lambda: [(yield x) for x in range(15)]
>>> print(*lamyield())
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Это неявно использует цикл for в понимании списка. Это невозможно с явным циклом while
или циклом for
вне понимания. Это потому, что лямбда-выражения в python могут содержать только выражения, а для написания явного цикла вам необходимо использовать операторы.
Примечание: этот синтаксис устарел в Python 3.7 и повысит SyntaxError
в Python 3.8
Ответ 2
Есть ли необходимость использовать yield
внутри lambda
, если вы можете переписать его с генератором, чтобы?
In[1]: x = (i for i in range(15))
In[2]: x
Out[2]: <generator object <genexpr> at 0x7fbdc69c3f10>
In[3]: print(*x)
Out[3]: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
In[4]: x = (i for i in range(0, 15))
In[5]: x.__next__()
Out[5]: 0
In[6]: next(x)
Out[6]: 1
Ответ 3
На самом деле вы можете проходить через лямбду полезными способами, просто приведенный вами пример не является хорошим вариантом использования.
Один из примеров, когда вы можете захотеть использовать yield
внутри lambda
, может состоять в том, чтобы лениво выполнять дорогостоящие функции только при необходимости. Вот так:
for check, args in (lambda: (
(yield (expensive_check1(), ["foo", "bar"])),
(yield (expensive_check2(), ["baz"])),
(yield (expensive_check3(), []), [])),
))():
if check:
x = do_the_thing(*args)
break
else:
raise Exception("oh noes!!!")
* Обратите внимание, что этот синтаксис все еще будет работать в Python 3.8, так как он не использует yield
внутри понимания.