По какой причине в списке res значения элементов line меняется, нужно просто все значения line сделать подсписком res

Рейтинг: 0Ответов: 1Опубликовано: 03.02.2023
s = ['a', 'b', 'c']
line, res = [], []
n = len(s)
for i in range(1, n + 1):
    for j in range(n):
        line += s[j]
        if len(line) == i:
            print(line)
            res.append(line)
            line.pop(0)
    line = []
print(res)

Output:

['a']
['b']
['c']
['a', 'b']
['b', 'c']
['a', 'b', 'c']
[[], [], [], ['c'], ['c'], ['b', 'c']]

https://stepik.org/lesson/416753/step/14?auth=login&unit=406261

Ответы

▲ 2Принят

line является изменяемым объектом (списком), и когда вы добавляете его в res.append(line), в res добавляется ссылка на изменяемый объект line, поэтому, когда вы делаете line.pop(0), из line удаляется первый элемент, и точно так же он удаляется из того line, который вы добавили в res, потому что это один и тот же line. Самый простой способ - вставлять скопированное значение line, вместо исходного, например так:

s = ['a', 'b', 'c']
line, res = [], []
n = len(s)
for i in range(1, n + 1):
    for j in range(n):
        line += s[j]
        if len(line) == i:
            print(line)
            res.append(line[:])
            line.pop(0)
    line = []
print(res)

Итоговый res будет выглядеть так:

[['a'], ['b'], ['c'], ['a', 'b'], ['b', 'c'], ['a', 'b', 'c']]

(обратите внимание на добавленную конструкцию [:]). Она создает копию списка line, от первого до последнего элемента. Если такой способ вам не понятен, почитайте про срезы в питоне, или используйте на 9й строке такой способ: res.append(line.copy()) или res.append(list(line))