简体   繁体   中英

Looping through a list of lists

I am new to programming and I have this basic problem I cannot fix. I simplified it as much as possible. In this simplified version, I am iterating through an empty list. I just want to store the indices in the "symmetric matrix":

n = 2
B = [[None] * n] * n
print B, "\n"
for i in range(n):
    for j in range(n):
        B[i][j] = [i, j]
        print B

Initially, the list looks like this:

[[None, None], [None, None]] 

After looping trough, I would expect the print-out to be:

[[[0, 0], None], [None, None]]
[[[0, 0], [0, 1]], [None, None]]
[[[1, 0], [0, 1]], [[1, 0], None]]
[[[1, 0], [1, 1]], [[1, 0], [1, 1]]]

Instead, I get this:

[[[0, 0], None], [[0, 0], None]]
[[[0, 0], [0, 1]], [[0, 0], [0, 1]]]
[[[1, 0], [0, 1]], [[1, 0], [0, 1]]]
[[[1, 0], [1, 1]], [[1, 0], [1, 1]]]

What am I missing? Thanks for helping out...

Your initialization creates two references to the same list:

n=2
B=[[None]*n]*n
for x in B:
     print id(x)

Output:

4534759576
4534759576

What you need instead of the current way you're defining B is n "fresh" instances of the sublist:

B = [[None] * n for _ in range(n)]

which is equivalent to but shorter and (for a Pythonista) more readable than:

B = []
for _ in range(n):
    B.append([None] * n)

This is because lists in Python are not values but objects; ie they are not copied by default. For example:

>>> a = []
>>> b = [a, a]  # list of 2 items, both pointing to the same list instance
>>> b[0].append(1)  # b[0] refers to the same list instance also referenced by a
>>> print b
[[1], [1]]

whereas:

>>> b = [[], []]  # list of 2 distinct sublists
>>> b[0].append(1)
>>> print b
[[1], []]

If you apply that knowledge to

B = [[None] * n] * n

you'll see there's an error in the construction—you're creating a list that contains another list of n None values; you're then "upsizing" the list to contain n of such lists; however, the same list instance will be used just like in the above, more trivial examples.

PS more accurately, everything in Python is an object not a value, except in cases where the object is immutable, such as int s and float s and str s etc, it is as if they are values and are always copied—this is because if an object is immutable, you might as well pretend a new reference to it is a new copy of it, because it looks the same and cannot be modified.

Here is how you could do, what you want:

    n=2
    B = [[None for i in range(n)] for i in range(n)]
    print B, "\n"
    for i in range(n):
        for j in range(n):
        B[i][j] = [i, j]
        print B

The key to understanding what is happening here is understanding that you are creating lists with shared references when you use the [[None]*n]*n method. Have a look at this visualisation of what your code does, it should make things more clear. This blog post also explains how names and values work in Python.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM