Python: список списков

Запуск кода

listoflists = []
list = []
for i in range(0,10):
    list.append(i)
    if len(list)>3:
        list.remove(list[0])
        listoflists.append((list, list[0]))
print listoflists

возвращает

[([7, 8, 9], 0), ([7, 8, 9], 0), ([7, 8, 9], 0), ([7, 8, 9], 1), ([7, 8, 9], 2), ([7, 8, 9], 3), ([7, 8, 9], 4), ([7, 8, 9], 5), ([7, 8, 9], 6), ([7, 8, 9], 7)]

поэтому так или иначе первый аргумент каждого кортежа (списка) обновляется каждый раз в списке списков, но второй список аргументов [0] - нет. Может кто-нибудь объяснить, что происходит здесь, и предложить способ исправить это? Я хотел бы выводить

[([0],0), ([0,1],0), ...

Ответы

Ответ 1

Списки являются изменяемыми типами - для создания копии (а не просто прохождения одного и того же списка) вам нужно сделать это явно:

    listoflists.append((list[:], list[0]))

Однако list уже является именем встроенного Python - было бы лучше не использовать это имя для вашей переменной. Здесь версия, которая не использует list как имя переменной и создает копию:

listoflists = []
a_list = []
for i in range(0,10):
    a_list.append(i)
    if len(a_list)>3:
        a_list.remove(a_list[0])
        listoflists.append((list(a_list), a_list[0]))
print listoflists

Обратите внимание, что я продемонстрировал два разных способа сделать копию списка выше: [:] и list().

Первый, [:], создает срез (обычно часто используемый для получения только части списка), который, как оказалось, содержит весь список и, следовательно, является фактически копией списка.

Второй, list(), использует фактический конструктор типа list для создания нового списка, который имеет содержимое, равное первому списку. (Я не использовал его в первом примере, потому что вы переписывали это имя в своем коде, что является хорошим примером того, почему вы этого не хотите!)

Ответ 2

Я пришел сюда, потому что я новичок в python и ленив, поэтому я искал пример, чтобы создать список из 2 списков, через некоторое время понял, что тема здесь может быть неправильной... это код для создания списка списков:

listoflists = []
for i in range(0,2):
    sublist = []
    for j in range(0,10)
        sublist.append((i,j))
    listoflists.append(sublist)
print listoflists

этот вывод   [      [0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), ( 0, 8), (0, 9)],      [1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), ( 1, 8), (1, 9)]   ]

Проблема с вашим кодом, похоже, заключается в создании кортежа с вашим списком, и вы получаете ссылку на список вместо копии. То, что я думаю, должно подпадать под тему кортежа...

Ответ 3

Во-первых, я настоятельно рекомендую переименовать переменную list в другое. list - это имя встроенного конструктора списков, и вы скрываете его нормальную функцию. Я переименую list в a следующим образом.

Имена Python - это ссылки, привязанные к объектам. Это означает, что, если вы не создаете более одного списка, всякий раз, когда вы используете a, он ссылается на тот же фактический объект списка, что и в последний раз. Поэтому, когда вы вызываете

listoflists.append((a, a[0]))

вы можете позже изменить a, и он изменит то, на что указывает первый элемент этого кортежа. Это не происходит с a[0], потому что объект (который является целым числом), на который указывает a[0], не изменяется (хотя a[0] указывает на разные объекты за время выполнения вашего кода).

Вы можете создать копию всего списка a с помощью конструктора list:

listoflists.append((list(a), a[0]))

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

listoflists.append((a[:], a[0]))

Ответ 4

При запуске кода

listoflists.append((list, list[0]))

Вы не (как я думаю, вы ожидаете) добавили копию list в конец listoflists. Что вы делаете, это добавить ссылку на list в конец listoflists. Таким образом, каждый раз, когда вы обновляете list, он обновляет каждую ссылку на list, которая в этом случае является каждым элементом в listoflists

Вместо этого вы можете сделать следующее:

listoflists = []
for i in range(1, 10):
    listoflists.append((range(i), 0))

Ответ 5

Переменная списка (которую я бы рекомендовал переименовать в нечто более разумное) является ссылкой на объект списка, который можно изменить.

В строке

listoflists.append((list, list[0]))

Фактически вы только добавляете ссылку на ссылку на объект переменной списка. У вас есть несколько возможностей для создания копии списка, поэтому listoflists содержит значения, которые вы ожидаете:

Использовать библиотеку копий

import copy
listoflists.append((copy.copy(list), list[0]))

использовать нотацию фрагмента

listoflists.append((list[:], list[0]))

Ответ 6

Вы также не сможете получить вывод, на который вы надеетесь, до тех пор, пока вы добавите listoflists только внутри if-clause.

Попробуйте что-то вроде этого:

import copy

listoflists = []
list = []
for i in range(0,10):
    list.append(i)
    if len(list)>3:
        list.remove(list[0])
    listoflists.append((copy.copy(list), copy.copy(list[0])))
print(listoflists)

Ответ 7

Путешественник во времени здесь

List_of_list =[([z for z in range(x-2,x+1) if z >= 0],y) for y in range(10) for x in range(10)]

Это должно сработать. И вывод такой:

[([0], 0), ([0, 1], 0), ([0, 1, 2], 0), ([1, 2, 3], 0), ([2, 3, 4], 0),  ([3, 4, 5], 0), ([4, 5, 6], 0), ([5, 6, 7], 0), ([6, 7, 8], 0), ([7, 8, 9], 0), ([0], 1), ([0, 1], 1), ([0, 1, 2], 1), ([1, 2, 3], 1), ([2, 3, 4], 1), ([3, 4, 5], 1), ([4, 5, 6], 1), ([5, 6, 7], 1), ([6, 7, 8], 1), ([7, 8, 9], 1), ([0], 2), ([0, 1], 2), ([0, 1, 2], 2), ([1, 2, 3], 2), ([2, 3, 4], 2), ([3, 4, 5], 2), ([4, 5, 6], 2), ([5, 6, 7], 2), ([6, 7, 8], 2), ([7, 8, 9], 2), ([0], 3), ([0, 1], 3), ([0, 1, 2], 3), ([1, 2, 3], 3), ([2, 3, 4], 3), ([3, 4, 5], 3), ([4, 5, 6], 3), ([5, 6, 7], 3), ([6, 7, 8], 3), ([7, 8, 9], 3), ([0], 4), ([0, 1], 4), ([0, 1, 2], 4), ([1, 2, 3], 4), ([2, 3, 4], 4), ([3, 4, 5], 4), ([4, 5, 6], 4), ([5, 6, 7], 4), ([6, 7, 8], 4), ([7, 8, 9], 4), ([0], 5), ([0, 1], 5), ([0, 1, 2], 5), ([1, 2, 3], 5), ([2, 3, 4], 5), ([3, 4, 5], 5), ([4, 5, 6], 5), ([5, 6, 7], 5), ([6, 7, 8], 5), ([7, 8, 9], 5), ([0], 6), ([0, 1], 6), ([0, 1, 2], 6), ([1, 2, 3], 6), ([2, 3, 4], 6), ([3, 4, 5], 6), ([4, 5, 6], 6), ([5, 6, 7], 6), ([6, 7, 8], 6), ([7, 8, 9], 6), ([0], 7), ([0, 1], 7), ([0, 1, 2], 7), ([1, 2, 3], 7), ([2, 3, 4], 7), ([3, 4, 5], 7), ([4, 5, 6], 7), ([5, 6, 7], 7), ([6, 7, 8], 7), ([7, 8, 9], 7), ([0], 8), ([0, 1], 8), ([0, 1, 2], 8), ([1, 2, 3], 8), ([2, 3, 4], 8), ([3, 4, 5], 8), ([4, 5, 6], 8), ([5, 6, 7], 8), ([6, 7, 8], 8), ([7, 8, 9], 8), ([0], 9), ([0, 1], 9), ([0, 1, 2], 9), ([1, 2, 3], 9), ([2, 3, 4], 9), ([3, 4, 5], 9), ([4, 5, 6], 9), ([5, 6, 7], 9), ([6, 7, 8], 9), ([7, 8, 9], 9)]    

Это делается путем понимания списка (что делает возможным циклическое перемещение элементов в списке с помощью однострочного кода). Логика этого однострочного кода следующая:

(1) для x в диапазоне (10) и для y в диапазоне (10) используются для двух независимых циклов внутри списка

(2) (список, y) - это общий термин цикла, поэтому он помещается перед двумя в (1)

(3) длина списка в (2) не может превышать 3, а список зависит от x, поэтому

[z for z in range(x-2,x+1)] 

используется

(4) поскольку z начинается с нуля, а диапазон (x -2, x + 1) начинается с -2, а это не то, что нам нужно, поэтому условное утверждение, если z> = 0, помещается в конец списка в (2)

[z for z in range(x-2,x+1) if z >= 0] 

Ответ 8

Я использую Python 3.6.8

Я попытался user110954 ответить, он выдал ошибку в for j in range(0,10) & print listoflists

Код работает для меня -

listoflists = []
for i in range(0,2):
    sublist = []
    for j in range(0,10):
        sublist.append((i,j))
    listoflists.append(sublist)

print (listoflists)