0

I tried encoding groups of information (temp1) to a list (temp2) using a script and noticed that all elements of temp2 are the same and is the last value of temp1 when I did this:

if __name__ == '__main__':
    temp1 = []
    temp2 = []
    x = ''
    
    for i in range(0, 10):
        for j in range(0, 10):
            x = str(input(f'Data {j + 1} of {i + 1}: '))
            temp1.append(x)
        temp2.append(temp1)
        temp1.clear()
    print(temp1)

For explanation purposes, say I have three groups, and each group as three elements. What I am expecting is [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]. However, the list that I get is [['g', 'h', 'i'], ['g', 'h', 'i'], ['g', 'h', 'i']].

But when I used a function that returns a list, it works as intended.

def foo(lb: int, ub: int) -> list:
    temp = []
    y = ''
    
    for i in (lb, ub):
        y = str(input('Input: '))
        temp.append(y)
    return temp

if __name__ == '__main__':
    temp2 = []
    for j in range(0, 3):
        temp2.append(foo(0, 3))
    
    print(temp2)

Can I ask why this happens?

soupless
  • 113
  • 4
  • The first one returns list of empty lists to `temp2` and empty list to `temp1`. – sudden_appearance Mar 04 '22 at 10:12
  • Yes, after the outermost loop ends, `temp2` is a list of empty lists. But before it ends, the contents are repeated. It's as if the last run of the innermost loop returns an empty list, and all of the contents before will have the copy as the last one. – soupless Mar 04 '22 at 10:15

2 Answers2

0

I will describe what is going on right here, so you will understand what is wrong

if __name__ == '__main__':
    temp1 = []
    temp2 = []
    x = ''

You have created list references and x right here

for i in range(0, 10):
    for j in range(0, 10):
        x = str(input(f'Data {j + 1} of {i + 1}: '))
        temp1.append(x)

Here you ask for input and save it to temp1

    temp2.append(temp1)

Here you append the link!!!!! not the array copy to the temp2

    temp1.clear()

Here you are clearing temp1. temp2 now has reference to temp1 array which is empty.

The second iteration you still have temp2 array with one element referencing empty temp1. You didn't redeclare your temp1. So second iteration will save the same temp1 reference again and clear also temp1 afterwards. Same goes for third iteration. In the end you get temp2 with 3 absolutely same references to temp1. You can check it with

print(id(temp2[0]), id(temp2[1]), id(temp2[2]))  # 139769665143552 139769665143552 139769665143552 (all 3 are the same)

So the thing you need to do is reassign temp1 every first-level loop like so

if __name__ == '__main__':
    temp2 = []
    x = ''

    for i in range(0, 3):
        temp1 = []
        for j in range(0, 3):
            x = str(input(f'Data {j + 1} of {i + 1}: '))
            temp1.append(x)
        temp2.append(temp1)

    print(temp2)
    """
    Data 1 of 1: a
    Data 2 of 1: b
    Data 3 of 1: c
    Data 1 of 2: d
    Data 2 of 2: e
    Data 3 of 2: f
    Data 1 of 3: g
    Data 2 of 3: h
    Data 3 of 3: i
    [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
    """
sudden_appearance
  • 1,968
  • 1
  • 4
  • 15
0

Basically what you do is copy the list into temp2 using temp2.append(temp1). Remember, you didn't copy its content, you copied the list itself, and then the loop works again and adds it again, this happens 3 time and at the end, it returns same lists inside temp2. Work-around: you need to make a deep copy to avoid this scenario. To do it, you either need to do it manually looping over all elements and pasting in temp2, otherwise, you can use this code snippet to make a deep copy containing all the elements.

temp2.append(temp1. deepcopy())

This'll create a deep copy through which you will get expected output.

Muhammad Ahmed
  • 318
  • 2
  • 8