簡體   English   中英

Python生成器

[英]Python Generator

def countDown(i):
    if i<> 0:
        For j in countDown( i - 1 ):
            yield j
        yield i                 
if __name__ == '__main__':

    for k in countDown(5):
        print k
        if k == 6 : break

在調試此代碼時,執行路徑與我預期的有所不同。 我的期望:countDown中的“ for”循環將遞歸調用該函數:countDown(4),countDown(3),countDown(2)以及countDown(1)和countDown(0)。 此時,如果不滿足條件,則開始“返回階段”,將執行Yield j。 這會將控件返回到“ main”函數中的for循環。

此for循環的下一次迭代再次調用countDown(5),該計數從最后一個Yield-Yield j開始。 這將執行for ... countdown(i-1)循環,並調用countDown(4),countDown(3),CountDown(2).. countDown(0)。 然后,“返回階段”開始並達到第一個Yield j(現在j從較早的第一遍開始遞增)。 這將使控制返回到“ main”函數中的for循環。

在調試時,這是我發現的內容:

1)如果i <> 0失敗(如遞歸末尾所述),則似乎執行Yield i。 然后似乎在控制權返回到k ... main之前彈出堆棧中的每個countDown。

2)在第二次迭代中,對於g中的k,堆棧進入返回階段-堆棧的頂部到底部是countDown(1),countDown(2),countDown(3),countDown(4),然后開始“返回階段”。 在該階段,j的值為“ 1”。 所以。 在開始返回階段之前,為什么它不會下降到countDown(0),其中i = 1?

誰能解釋這應該如何工作-遞歸和Generator函數的組合? 很抱歉,漫長的大風過后-沒有其他方法可以解釋它

謝謝。 伙計們的答復。

我到目前為止的理解:

1)在countDown(5)中k的第一次迭代:入口

功能說明

======== ===========
countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)中j的cou​​ntDown(2)

countDown(0)中j的cou​​ntDown(1)

countDown(0)如果語句失敗,則不返回任何內容

返回階段

一種)

countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)中j的cou​​ntDown(2)

CountDown(0)中j的CountDown(1)=無-因為countDown(0)不返回任何內容(因為如果條件失敗),j沒有任何結果,因此不會屈服j(收益j在For循環內) 。 但是,收益率我被執行了,我這里是1。 因此,countdown(1)將1返回上一個遞歸。

b)countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)= 1中j的cou​​ntDown(2)現在j的值為'1'。 因此,countdown(1)中的For j為true。 因此,它計算出Yield j =1。結果countDown(2)返回1。這是j分配給i的地方。

c)countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)= 1中j的cou​​ntDown(3)現在j的值為'1'。 因此,countdown(2)中的For j為true。 因此,它將得出Yield j =1。結果countDown(3)返回1

...

e)countDown(4)= 1中j的Countdown(5)由count Down(4)返回的值為1。 因此,j為1。因此,執行了countDown(4)中的for j。

               The next statement Yield j  within the For statement gets exceuted.
                it returns 1.

對於countDow(5)中的k,k將得到1。這將被打印出來。

2)現在到countDown(5)中for k的第二次迭代

遞歸“條目”

=================

在countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3),其中j = 1

在countDown(1)中j的cou​​ntdown(2),其中j = 1

countdown(1)執行Yield i,因為上一次迭代步驟a)yield是最后執行的語句

遞歸返回

a)countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3),其中j = 1

countDown(1)中j的cou​​ntdown(2),其中j = 1 Countdown(1)返回值1,j已經具有值1,因此,它執行下一步,即產生產量i,其中i =2。countDown( 2)返回收益率i = 2

b)countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3)
因為countDown(2)返回2,所以j得到這個新值j = 2產生j得到執行c)

在countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

countDown(3)中j的cou​​ntdown(4),其中j = 1,因為countdown(3)返回值2,如b)所示,j的新值為2

...

e)countDown(4)中j的cou​​ntdown(5)變為2

也許這可以闡明看漲/收益的發生順序:

編輯:

def countDown(i):
    if i<> 0:
        for j in countDown( i - 1 ):
            yield 'inner : ' + str(j)
        yield 'outer : ' + str(i)   

>>> for k in countDown(5): print k
... 
inner : inner : inner : inner : outer : 1
inner : inner : inner : outer : 2
inner : inner : outer : 3
inner : outer : 4
outer : 5

它一直推到i為0,這不會產生任何結果,因此countDown(1)中的for循環也不會。 接下來,countDown(1)產生1,該計數返回由countDown(2),countDown(3),countDown(4)和countDown(5)產生。 換句話說,產生的值將返回到前一個調用方,在此之前,它將被一次又一次地產生,直到取消調用堆棧。 下一個要用盡的生成器是countDown(2),它產生2到countDown(3),countDown(4)和countDown(5)。 生成器連續排放,直到最后countDown(5)產生5。

假設您遍歷countDown(5)

  1. countDown(5)獲取下一個countDown(4)
  2. countDown(4)獲取下一個countDown(3)
  3. countDown(3)獲取下一個countDown(2)
  4. countDown(2)獲取下一個countDown(1)
  5. countDown(1)獲取下一個countDown(0)
  6. countDown(0) yield i = 0, countDown(0)停止
  7. countDown(1) yield j = 0
  8. countDown(2) yield j = 0
  9. countDown(3) yield j = 0
  10. countDown(4) yield j = 0
  11. countDown(5) yield j = 0
  12. countDown(5)獲取下一個countDown(4)
  13. countDown(4)獲取下一個countDown(3)
  14. countDown(3)獲取下一個countDown(2)
  15. countDown(2)獲取下一個countDown(1)
  16. countDown(1) yield i = 1, countDown(1) stop
  17. countDown(2) yield j = 1
  18. countDown(3) yield j = 1
  19. countDown(4) yield j = 1
  20. countDown(5) yield j = 1
  21. countDown(5)獲取下一個countDown(4)
  22. countDown(4)獲取下一個countDown(3)
  23. countDown(3)獲取下一個countDown(2)
  24. countDown(2) yield i = 2, countDown(2)停止
  25. countDown(3) yield j = 2
  26. countDown(4) yield j = 2
  27. countDown(5) yield j = 2
  28. countDown(5)獲取下一個countDown(4)
  29. countDown(4)獲取下一個countDown(3)
  30. countDown(3) yield i = 3, countDown(3)停止
  31. countDown(4) yield j = 3
  32. countDown(5) yield j = 3
  33. countDown(5)獲取下一個countDown(4)
  34. countDown(4) yield i = 4, countDown(4)停止
  35. countDown(5) yield j = 4
  36. countDown(5) yield i = 5, countDown(5)停止

不知道為什么我無法編輯您的帖子。

def countDown(i):
    if i <> 0:
        For j in countDown( i - 1 ):
            yield j
    yield i

看來您只想倒數,所以yield i 然后您將得到4 3 2 1 0而不是0 1 2 3 4

def countDown(i):
    yield i
    if i <> 0:
        For j in countDown( i - 1 ):
            yield j

謝謝。 伙計們的答復。

經過進一步調試:

1)第一次迭代-對於countDown(5)中的k:

遞歸進入階段

功能說明

======== ===========
countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)中j的cou​​ntDown(2)

countDown(0)中j的cou​​ntDown(1)

countDown(0)如果語句失敗,則不返回任何內容

遞歸返回階段

一種)

countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)中j的cou​​ntDown(2)

CountDown(0)中j的CountDown(1)=無-因為countDown(0)不返回任何內容(因為如果條件失敗),j沒有任何結果,因此不會屈服j(收益j在For循環內) 。 但是,收益率我被執行了,我這里是1。 因此,countdown(1)將1返回上一個遞歸。

b)countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)中j的cou​​ntDown(3)

countDown(1)= 1中j的cou​​ntDown(2)現在j的值為'1'。 因此,countdown(1)中的For j為true。 因此,它計算出Yield j =1。結果countDown(2)返回1。這是j分配給i的地方。

c)countDown(4)中j的cou​​ntdown(5)

countDown(3)中j的cou​​ntdown(4)

countDown(2)= 1中j的cou​​ntDown(3)現在j的值為'1'。 因此,countdown(2)中的For j為true。 因此,它將得出Yield j =1。結果countDown(3)返回1

...

e)countDown(4)= 1中j的Countdown(5)由count Down(4)返回的值為1。 因此,j為1。因此,執行了countDown(4)中的for j。

               The next statement Yield j  within the For statement gets exceuted.
                it returns 1.

對於countDow(5)中的k,k將得到1。這將被打印出來。

2)現在到第二次迭代-對於countDown(5)中的k

遞歸進入階段

在countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3),其中j = 1

在countDown(1)中j的cou​​ntdown(2),其中j = 1

countdown(1)執行Yield i,因為上一次迭代步驟a)yield是最后執行的語句

遞歸返回

a)countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3),其中j = 1

countDown(1)中j的cou​​ntdown(2),其中j = 1 Countdown(1)返回值1,j已經具有值1,因此,它執行下一步,即產生產量i,其中i =2。countDown( 2)返回收益率i = 2

b)countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

在countDown(3)中j的cou​​ntdown(4),其中j = 1

countDown(2)中j的cou​​ntDown(3)
因為countDown(2)返回2,所以j得到這個新值j = 2產生j得到執行c)

在countDown(4)中j的cou​​ntdown(5),其中j = 1(Y是最后執行的語句)

countDown(3)中j的cou​​ntdown(4),其中j = 1,因為countdown(3)返回值2,如b)所示,j的新值為2

...

e)countDown(4)中j的cou​​ntdown(5)變為2

暫無
暫無

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

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