python:lambda,yield-statement/expression和loops(Clarify)

the*_*Dog 21 python lambda loops generator python-3.x

TLDR: 我们可以yield在一个lambda?中实现或生成语句(带循环)?

我的问题是澄清:

是否可以使用yield实现以下简单循环函数

def loopyield():
   for x in range(0,15):
      yield x
print(*loopyield())
Run Code Online (Sandbox Code Playgroud)

结果有误:

lamyield=lambda x: yield x for x in range(0,15)
                       ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

看起来像是,它期待一些东西作为不成文的返回语句的正确操作数,但发现yeild并且变得困惑.

是否有合适的合法方式在循环中实现这一目标?

旁注:yield可以是语句/表达式取决于你问的对象:yield - statement还是expression?

最终答案: yield可以与lambda一起使用,但限制(单行)使它无用. for/while在lambda中不可能,因为它们不是表达式. -user2357112隐式for循环可以使用列表推导,并且yield在列表推导中有效.- wim

判决 -显式循环不可能,因为python中的lambdas只能包含表达式,并且要编写显式循环,您需要使用语句.-wim

wim*_*wim 27

您似乎尝试创建的单行实际上在技术上可以使用lambda,您只需要帮助解析器更多:

>>> 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
Run Code Online (Sandbox Code Playgroud)

这在列表推导中隐式使用for循环.在理解之外,不可能使用显式while循环或for循环.那是因为python中的lambdas只能包含表达式,并且要编写显式循环,您需要使用语句.

注意:在Python 3.7中不推荐使用这种语法,并且将SyntaxError在Python 3.8中引用

  • 请注意,Python 2上的结果完全不同.这个代码在一个非常微妙的方面依赖于这样的事实:在Python 3中,列表理解是用`lambda`创建的匿名函数中的*another*anonymous函数实现的. (5认同)
  • 你也可以做这样的事情——它会延迟计算每个函数,并且不会在 3.8 中被弃用:`lamyield = lambda: ((yield lucky_func1()), (yield lucky_func2()), (yield lucky_func3())) ` (2认同)

Ric*_*ica 6

实际上,您可以以有用的方式循环 lambda,只是您提供的示例不是一个很好的用例。

您可能希望yield在 a 内部使用的一个实例lambda可能是仅在需要时延迟执行昂贵的函数。就像这样:

def expensive_check1():
    print("expensive_check1")
    return True


def expensive_check2():
    print("expensive_check2")
    return True


def expensive_check3():
    print("expensive_check3")
    return True


def do_the_thing(*args):
    print(args)


if __name__=="__main__":
    for check, args in (lambda: (
                                (yield (expensive_check1(), ["foo", "bar"])), 
                                (yield (expensive_check2(), ["baz"])),
                                (yield (expensive_check3(), [])),
                        ))():
        if check:
            do_the_thing(*args)
            continue
        raise Exception("oh noes!!!")
    else:
        print("all OK!")
Run Code Online (Sandbox Code Playgroud)

输出:

expensive_check1
('foo', 'bar')
expensive_check2
('baz',)
expensive_check3
()
all OK!
Run Code Online (Sandbox Code Playgroud)

请注意,昂贵的检查仅在每个循环开始时发生,而不是一次全部发生。另请注意,此语法在 Python 3.8+ 中仍然有效,因为它不使用yield推导式的内部。


N.C*_*.C. 5

如果可以使用generator重写它,是否有必要在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
Run Code Online (Sandbox Code Playgroud)