生成器函数在将其转换为列表时的奇怪行为

问题描述 投票:0回答:1

我正在尝试获取列表的每个状态,同时排序以进行可视化。 所以用bubbleSort算法

我做了一个生成器函数

def bubbleSort(arr): 

    n = len(arr)

    yield arr  # yielding original state

    for i in range(n):

        swapped = False
        
        for j in range(0, n-i-1): 
        
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = True

                yield arr   # yielding every state during bubbleSort
                
        if (swapped == False):
            break

arr = [64, 34, 25, 12, 22, 11, 90]

generator=bubbleSort(arr)

for i in generator:
    print(i)

现在这期望的输出.

[64, 34, 25, 12, 22, 11, 90]
[34, 64, 25, 12, 22, 11, 90]       
[34, 25, 64, 12, 22, 11, 90]
[34, 25, 12, 64, 22, 11, 90]
[34, 25, 12, 22, 64, 11, 90]
[34, 25, 12, 22, 11, 64, 90]
[25, 34, 12, 22, 11, 64, 90]
[25, 12, 34, 22, 11, 64, 90]
[25, 12, 22, 34, 11, 64, 90]
[25, 12, 22, 11, 34, 64, 90]
[12, 25, 22, 11, 34, 64, 90]
[12, 22, 25, 11, 34, 64, 90]
[12, 22, 11, 25, 34, 64, 90]
[12, 11, 22, 25, 34, 64, 90]
[11, 12, 22, 25, 34, 64, 90]

但是如果我使用以下任何一种方式将其转换为列表:(一次一个)

#1
print(list(generator))

#2
l=[i for i in generator] 
print(l)

#3
l=[]
for i in generator:    
    l.append(i)
print(l)

#4
l=[*generator]
print(l)

它会给我 o/p 如下:(all states are already sorted or last states)

[[11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90]] 

现在我不明白为什么会这样,但是,当我这样做时,这让我更加困惑 这些中的任何一个给了我想要的o/p

#1
l=[list(i) for i in generator]  #list(i)
print(l)

#2
l=[i.copy() for i in generator]  #i.copy()
print(l)

#3
l=[]
for i in generator: 
    l.append(list(i))  #list(i)
print(l)

#4
l=[]
for i in generator:
    l.append(i.copy()) #i.copy()
print(l)

o/p:

[[64, 34, 25, 12, 22, 11, 90], [34, 64, 25, 12, 22, 11, 90], [34, 25, 64, 12, 22, 11, 90], [34, 25, 12, 64, 22, 11, 90], [34, 25, 12, 22, 64, 11, 90], [34, 25, 12, 22, 11, 64, 90], [25, 34, 12, 22, 11, 64, 90], [25, 12, 34, 22, 11, 64, 90], [25, 12, 22, 34, 11, 64, 90], [25, 12, 22, 11, 34, 64, 90], [12, 25, 22, 11, 34, 64, 90], [12, 22, 25, 11, 34, 64, 90], [12, 22, 11, 25, 34, 64, 90], [12, 11, 22, 25, 34, 64, 90], [11, 12, 22, 25, 34, 64, 90]]

谁能给我解释一下为什么最后两个输入之间的输出差异? 当我为生成器中的每个状态i.copy()list(i)时有什么变化? 感谢阅读。

python list generator
1个回答
0
投票

有一个单一的

arr
对象在生成器中被变异。

如果你在突变之间打印它,你会得到每个单独状态的快照,因为

arr
的当前状态在它改变之前打印到控制台。

但是,当您在列表理解中捕获该

arr
对象时,您只有一个列表,其中包含对该对象的一堆引用,因此随着
arr
的变化,列表中的每个条目也会发生变化。

如果你想改变它,你可以

yield arr.copy()
在你的生成器中,以确保你总是产生一个不会随着生成器继续迭代而改变的唯一副本。这与您在生成器外部调用
copy()
list()
时所看到的效果相同(这两种方法都会产生一个新副本,当在生成器内部修改
arr
时,该副本不会更改)。

© www.soinside.com 2019 - 2024. All rights reserved.