Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
混淆python屈服行为_Python_Generator_Yield - Fatal编程技术网

混淆python屈服行为

混淆python屈服行为,python,generator,yield,Python,Generator,Yield,今天我遇到了一个有趣的行为,yield,我真的不明白。这是我的密码: def a(): def b(x): print("entering b.") yield 0 if x == 0: print("calling b.") b(x + 1) print("return from b.") print("leaving b.") for x

今天我遇到了一个有趣的行为,
yield
,我真的不明白。这是我的密码:

def a():
    def b(x):
        print("entering b.")
        yield 0
        if x == 0:
            print("calling b.")
            b(x + 1)
            print("return from b.")
        print("leaving b.")

    for x in b(0):
        yield x

for x in a():
    print(x)
这将产生:

entering b.
0
calling b.
return from b.
leaving b.
让我非常困惑的是,显式调用
b(x+1)
并没有调用
b
(!),Python也没有给出任何错误或异常

现在,显然上面代码中的错误是,
b(x+1)
应该真正产生
b
产生的值-因此应该是这样的:

for x in b(x + 1):
  yield x
然后事情就开始了

然而,这是否是我应该知道的
yield
的问题?

调用
b(x+1)
,但直到在调用函数的上下文中yield之后才执行

使用
yield from
生成调用
b()
生成的所有值并执行主体:

def a():
    def b(x):
        print("entering b.")
        yield 0
        if x == 0:
            print("calling b.")
            yield from b(x + 1)
            print("return from b.")
        print("leaving b.")

    for x in b(0):
        yield x

for x in a():
    print(x)
(我已经投了更高的票),但我看到您仍在为此进行斗争,所以让我们试试这个变体:

def a():
    def b(x):
        print("entering b.")
        yield 0
        if x == 0:
            print("calling b.")
            temp = b(x + 1)
            print("calling b resulted in temp =", temp)
            print("return from b.")
        print("leaving b.")

    for x in b(0):
        yield x

for x in a():
    print(x)
现在让我们在Python3.x中运行它:

entering b.
0
calling b.
calling b resulted in temp = <generator object a.<locals>.b at 0x800ac9518>
return from b.
leaving b.
运行此命令将产生:

entering b.
0
calling b.
calling b resulted in temp = <generator object a.<locals>.b at 0x800ac9518>
entering b.
by doing next(temp), I got 0
return from b.
leaving b.

您可能希望
从b(x+1)获得收益
调用
b
不会运行主体。这不会因为是递归调用而改变。当你说“调用
b(x+1)
不会调用
b
”时,你从哪里调用它?如果它在
a
之外,则不会被调用,因为它在范围之外,因此会执行函数调用;生成的生成器被忽略。不确定
print(“calling b.”)
是否让您感到困惑?由于递归调用没有
产生
,因此也不会返回您可能期望的结果。。正如snake所指出的,我不明白如果调用b(x+1)(没有来自
收益),那么为什么不打印“输入b.”呢?@handras,因为生成器是懒惰的。它已经创建,但是它的代码不会运行,直到您尝试获取它的
下一个
元素。
b(x+1)
除了返回一个生成器之外,不会执行任何操作;您仍然需要在该生成器上迭代,以便主体执行。这就是
yield
return
@handras之间的区别,因为生成器应该是这样工作的。每当调用
next
时,它会停止并重新开始在yield语句处执行body。通常在被迭代的上下文中。
entering b.
0
calling b.
calling b resulted in temp = <generator object a.<locals>.b at 0x800ac9518>
entering b.
by doing next(temp), I got 0
return from b.
leaving b.
def a():
    def b(x):
        print("entering b.")
        yield 0
        if x == 0:
            print("calling b.")
            temp = b(x + 1)
            print("calling b resulted in temp =", temp)
            y = next(temp)
            print("by doing next(temp), I got", y)
            try:
                print("about to re-enter temp")
                y = next(temp)
                print("with the second next(temp), I got", y)
            except StopIteration:
                print("with the second next(temp), I got StopIteration")
            print("return from b.")
        else:
            print("b had x =", x)
        print("leaving b.")

    for x in b(0):
        yield x

for x in a():
    print(x)