簡體   English   中英

令人困惑的python收益行為

[英]Confusing python yield behavior

我今天遇到了一個有趣的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 from產生該調用b()產生的所有值並執行body:

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)

現在讓我們在Python 3.x中運行它:

entering b.
0
calling b.
calling b resulted in temp = <generator object a.<locals>.b at 0x800ac9518>
return from b.
leaving b.

也就是說, temp被設置為調用b(x + 1) 結果結果就是這個<generator object ...>東西。

然后,你必須做發電機對象的東西,所以這里又是第三方案:

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)
            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.
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.

另一個答案中變體的yield from基本上意味着“繼續調用溫度並收益它產生的任何東西,直到它說它完成了”。 這個y = next(temp)調用一次temp。

為讀者練習:嘗試下面引用的第四個變體。 在運行它之前,嘗試預測一下你會看到的內容。 你看到你的預測嗎?

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM