Изменения в списках, отраженные по всем спискам неожиданно - PullRequest
513 голосов
/ 27 октября 2008

Мне нужно было создать список списков в Python, поэтому я набрал следующее:

myList = [[1] * 4] * 3

Список выглядел так:

[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]  

Затем я изменил одно из самых внутренних значений:

myList[0][0] = 5

Теперь мой список выглядит так:

[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]  

это не то, что я хотел или ожидал. Может кто-нибудь объяснить, что происходит и как обойти это?

Ответы [ 12 ]

1 голос
/ 10 июня 2015

Давайте перепишем ваш код следующим образом:

x = 1
y = [x]
z = y * 4

myList = [z] * 3

Затем запустите следующий код, чтобы сделать все более понятным. Код в основном печатает id s полученных объектов, что

Возвращает «идентичность» объекта

и поможет нам идентифицировать их и проанализировать, что происходит:

print("myList:")
for i, subList in enumerate(myList):
    print("\t[{}]: {}".format(i, id(subList)))
    for j, elem in enumerate(subList):
        print("\t\t[{}]: {}".format(j, id(elem)))

И вы получите следующий вывод:

x: 1
y: [1]
z: [1, 1, 1, 1]
myList:
    [0]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [1]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [2]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528

Так что теперь давайте пошагово. У вас есть x, что составляет 1, и один список элементов y, содержащий x. Ваш первый шаг - y * 4, который даст вам новый список z, который в основном равен [x, x, x, x], то есть он создаст новый список, который будет иметь 4 элемента, которые являются ссылками на исходный объект x. Чистый шаг довольно похож. Вы в основном делаете z * 3, что составляет [[x, x, x, x]] * 3 и возвращает [[x, x, x, x], [x, x, x, x], [x, x, x, x]], по той же причине, что и для первого шага.

0 голосов
/ 15 июля 2016

Используя встроенную функцию списка, вы можете сделать это

a
out:[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
#Displaying the list

a.remove(a[0])
out:[[1, 1, 1, 1], [1, 1, 1, 1]]
# Removed the first element of the list in which you want altered number

a.append([5,1,1,1])
out:[[1, 1, 1, 1], [1, 1, 1, 1], [5, 1, 1, 1]]
# append the element in the list but the appended element as you can see is appended in last but you want that in starting

a.reverse()
out:[[5, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
#So at last reverse the whole list to get the desired list
...