0

I wrote some Python code to add value to list, but the list didn't update value, so confuse:

lst = []
for i in ["2","3"]: 
    row = []
    row.append(i)
    
    for j in ["2","3"]:  
        row.append(j)
        print("row",row)
        lst.append(row)
        print("lst",lst)
        row.pop(-1)
    row.pop(-1)
            
print("lst",lst)

and here're the result:

lst [[], [], [], []]

the list's element didn't change in for loop and I think the cause's "lst.append(row)" but I don't know how to fix it. The result must be [[2,2],[2,3],[3,2],[3,3]]

mkrieger1
  • 19,194
  • 5
  • 54
  • 65

4 Answers4

3

You're making a very common mistake for new Python programmers that boils down to this:

lst = []
row = []  # lst and row are empty lists
row.append(1)  # now row is [1]
lst.append(row)  # lst is [[1]]
row.pop(-1)  # row becomes [] again
print(lst)  # surprise! lst is also [[]]

The last line tends to be surprising if you don't realise that adding a list to another list doesn't create a copy of the list, it just assigns the same list to that position of the other list. If you change the inner list through some other variable, that list gets changed, and thus you see that change reflected in the list that contains the list as well.

This would work as expected for your code:

lst = []
for i in ["2","3"]: 
    row = []
    row.append(i)
    
    for j in ["2","3"]:  
        row.append(j)
        print("row",row)
        lst.append(row.copy())  # note the difference here, .copy()
        print("lst",lst)
        row.pop(-1)
    row.pop(-1)
            
print("lst",lst)

It's still a bit overcomplicated, but the problem you had is resolved.

Grismar
  • 27,561
  • 4
  • 31
  • 54
0

They're empty because you pop everything from them.

Working version:

lst = []
for i in ["2","3"]: 
    for j in ["2","3"]:
        row = []
        row.append(i)
        row.append(j)
        lst.append(row)            
print("lst",lst)

Better version:

lst = []
for i in ["2","3"]: 
    for j in ["2","3"]:
        lst.append([i,j])
print("lst",lst)

List comprehension version:

lst = [[i,j]
       for i in ["2","3"]
       for j in ["2","3"]]
print("lst",lst)
Pychopath
  • 1,560
  • 1
  • 8
  • Actually here's full result: ```row ['2', '2'] lst [['2', '2']] row ['2', '3'] lst [['2', '3'], ['2', '3']] row ['3', '2'] lst [[], [], ['3', '2']] row ['3', '3'] lst [[], [], ['3', '3'], ['3', '3']] lst [[], [], [], []]``` Before using "pop" I did "lst.append(row)" but it's seem it just add variable row not value of variable. That's why I'm very confused – Huong Nguyen Feb 17 '22 at 23:40
  • @HuongNguyen You do append the value. But the value is a list. And then you keep making changes to that list. – Pychopath Feb 17 '22 at 23:48
0
from itertools import product

list(product([2,3], repeat=2))
John Giorgio
  • 634
  • 3
  • 10
0

row is an object inside lst. When you update row with row.pop(), you're removing your items from the row.

>>> lst = []
>>> n=0
>>> for i in ["2","3"]:
...     print("\n Running loop:%d"%(n))
...     print("1",lst)
...     row = [] #<- Your redefining row here, the old connection is gone
...     print("2",lst)
...     row.append(i)
...     for j in ["2","3"]:
...         row.append(j) #
...         lst.append(row) #<- you're duplicating the row here on the second pass through the "j" loop, so now you have the same object twice in lst
...         print("2.1",lst)
...         x=row.pop(-1) #<- you're removing the value from row that you just added...
...         print("2.2",lst)
...     x=row.pop(-1)  #<-  You have one value on row, and you're removing that one here
...     print("3",lst)
...     n+=1
...
...

 Running loop:0
1 []
2 []
2.1 [['2', '2']]
2.2 [['2']]
2.1 [['2', '3'], ['2', '3']]
2.2 [['2'], ['2']]
3 [[], []]

 Running loop:1
1 [[], []]
2 [[], []]
2.1 [[], [], ['3', '2']]
2.2 [[], [], ['3']]
2.1 [[], [], ['3', '3'], ['3', '3']]
2.2 [[], [], ['3'], ['3']]
3 [[], [], [], []]
>>>
>>> print("lst",lst)
lst [[], [], [], []]

You can insert your list on the fly like this, no need to make an intermediate.

>>> lst = []
>>> for i in ["2","3"]:
...     for j in ["2","3"]:
...         lst.append([i,j])
...
>>>
>>> print("lst",last)
lst [['2', '2'], ['2', '3'], ['3', '2'], ['3', '3']]
jeffpkamp
  • 2,732
  • 2
  • 27
  • 51
  • Actually here's full result: ```row ['2', '2'] lst [['2', '2']] row ['2', '3'] lst [['2', '3'], ['2', '3']] row ['3', '2'] lst [[], [], ['3', '2']] row ['3', '3'] lst [[], [], ['3', '3'], ['3', '3']] lst [[], [], [], []]``` Before "pop" I did "lst.append(row)", but you can see that it didn't save the value, "lst" changed every loop. Why? – Huong Nguyen Feb 17 '22 at 23:48
  • @HuongNguyen see the updated answer. – jeffpkamp Feb 18 '22 at 00:05
  • Note, you end up with 4 lists because you append the row ever pass at step 2.1. Since this is a 2x2 loop, 2x2 == 4. They are empty because you append once in loop `i` and once in loop `j`, and pop once in look `i` and once in loop `j`. – jeffpkamp Feb 18 '22 at 00:23