簡體   English   中英

為什么我不能改變我在使用yield時迭代的列表

[英]Why can't I change the list I'm iterating from when using yield

我在這里有一些可重現的代碼:

def test():
    a = [0, 1, 2, 3]
    for _ in range(len(a)):
        a.append(a.pop(0)) 
        for i in range(2,4):
            print(a)
            yield(i, a)

打印出:

[1, 2, 3, 0]
[1, 2, 3, 0]
[2, 3, 0, 1]
[2, 3, 0, 1]
[3, 0, 1, 2]
[3, 0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3]

這是我的預期,但當我做list(test())我得到:

[(2, [0, 1, 2, 3]),
 (3, [0, 1, 2, 3]),
 (2, [0, 1, 2, 3]),
 (3, [0, 1, 2, 3]),
 (2, [0, 1, 2, 3]),
 (3, [0, 1, 2, 3]),
 (2, [0, 1, 2, 3]),
 (3, [0, 1, 2, 3])]

為什么會這樣,我該怎么做才能解決這個問題?

因為你總是返回(i,a)現在a是對列表的引用 因此,您不斷返回對同一列表的引用 這是沒有問題的print語句,因為它立即打印的狀態, a 在那一刻

您可以返回列表的副本 ,例如:

def test():
    a = [0, 1, 2, 3]
    for _ in range(len(a)):
        a.append(a.pop(0)) 
        for i in range(2,4):
            print(a)
            yield(i, list(a))

你每次都會產生相同的列表,所以調用者的列表只有一堆對該列表的引用,每次調用時都會更新。 當您屈服時,您需要復制列表:

def test():
    a = [0, 1, 2, 3]
    for _ in range(len(a)):
        a.append(a.pop(0)) 
        for i in range(2,4):
            print(a)
            yield(i, a[:])

顯式更好的隱含:

import copy
def test():
    a = [0, 1, 2, 3]
    for _ in range(len(a)):
        a.append(a.pop(0)) 
        for i in range(2,4):
            print(a)
            yield(i, copy.copy(a))

最后得到一個元組列表,元組的第二個元素是相同的列表 您可能會注意到它們都等同於生成器生成的最后一個列表,而不是第一個列表; 列表正在改變,但元組都引用了同一個。

為清楚起見,請嘗試修改其中一個列表。 例如,如果你運行l[0][1].append(4) ,你就會得到

[(2, [0, 1, 2, 3, 4]),
 (3, [0, 1, 2, 3, 4]),
 (2, [0, 1, 2, 3, 4]),
 (3, [0, 1, 2, 3, 4]),
 (2, [0, 1, 2, 3, 4]),
 (3, [0, 1, 2, 3, 4]),
 (2, [0, 1, 2, 3, 4]),
 (3, [0, 1, 2, 3, 4])]

所有列表都附加了4個,因為只有一個列表。

如果要返回副本,有幾種方法。 您可以yield (i, a[:]) (使用切片表示法獲取副本), yield (i, list(a)) (使用list構造函數獲取副本)或yield (i, copy.copy(a)) (使用copy模塊)。

暫無
暫無

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

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