Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Weird behaviour of a generator function while converting it to a list

I am trying to get every state of a list while it is being sorted for a visualization.
So with bubbleSort algorithm

i made a generator function :

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)

Now this gives me my desired output.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[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]

But if i convert it to a list using any of these ways: (One at a time)

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

It will give me o/p as below : (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]] 

Now i don’t understand why this happens but , this gets even more confusing for me when i do
any of these and it gives me the desired 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]]

Can anyone explain it to me why the difference in outputs between last 2 inputs ?
What changes when i do i.copy() or list(i) for every state in the generator ?
Thanks for reading.

>Solution :

There is a single arr object that is being mutated inside the generator.

If you print it in between the mutations, you get a snapshot of each individual state, since the current state of arr is printed to the console before it changes.

When you capture that arr object in a list comprehension, though, you just have a list with a bunch of references to that one object, so as arr changes, so too does every entry in your list.

If you wanted to change that, you could yield arr.copy() inside your generator to make sure that you’re always yielding a unique copy that won’t change as the generator continues to iterate. This would have the same effect that you’re seeing when you call copy() or list() outside of the generator (either of those methods results in a new copy which does not change when arr is modified inside the generator).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading