Итерация по пустому 2d против непустого python

#python #arrays

#python #массивы

Вопрос:

Я хочу выполнить итерацию по списку 2d python. Однако я заметил разницу, когда он выполняет итерацию по пустому 2d-массиву по сравнению с непустым 2d-массивом. Например

     mat = [[]] * n
    print("initial", mat)
    
    count = 0
    for row in mat:
        print("row:", row)
        for _ in range(2):
            print(_)
            row.append(count)
            count  = 1
            print(mat)
        print("n")
    return mat
mat = empty(2)
 

Вот что он печатает. Он добавляет счетчик к обоим подмассивам, а не только к одному

 initial [[], []]
row: []
0
[[0], [0]]
1
[[0, 1], [0, 1]]


row: [0, 1]
0
[[0, 1, 2], [0, 1, 2]]
1
[[0, 1, 2, 3], [0, 1, 2, 3]]
 

Однако, когда я меняю код на этот

 def nonempty(n):
    mat = [['a'],['b']]
    print("initial", mat)
    
    count = 0
    for row in mat:
        print("row:", row)
        for _ in range(2):
            print(_)
            row.append(count)
            count  = 1
            print(mat)
        print("n")
    return mat
mat = empty(2)
 

Вот что он печатает

 initial [['a'], ['b']]
row: ['a']
0
[['a', 0], ['b']]
1
[['a', 0, 1], ['b']]


row: ['b']
0
[['a', 0, 1], ['b', 2]]
1
[['a', 0, 1], ['b', 2, 3]]
 

В этом случае он изменяет только один вложенный массив за раз вместо двух. Кто-нибудь может сказать мне, почему это происходит. Это из-за того, как работают списки python?

Ответ №1:

Проблема в mat = [[]] * n том, что все пустые массивы на самом деле являются одним и тем же экземпляром

Тот же объект

http://pythontutor.com/visualize.html#code=mat = [[]] * 5
mat[1].append(1)
print(mat)amp;cumulative=falseamp;curInstr=3amp;heapPrimitives=trueamp;mode=displayamp;origin=opt-frontend.jsamp;py=3amp;rawInputLstJSON=[]amp;textReferences=false

Таким образом, вы можете создать свой mat, mat = [ list() for _ in range(n) ] чтобы быть уверенным, что пустой список не является общим.