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 внутри понимания.