что-то неожиданное в python при разработке вложенного списка

#python-3.x

#python-3.x

Вопрос:

я хочу превратить ‘a’ во вложенный список: поэтому я создаю цикл while:

 a = [1,2,3,4,5,6,7,8,9,10,11,12]
ll = l = []
m,f,k = 1,0,4

while m <= 3:

    l.append(a[int(f):int(k)])
    f = f   4
    k = k   4

    ll.append(l)
    m = m 1

print(ll)
  

я хочу [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]] , а не [[1, 2, 3, 4], [...], [5, 6, 7, 8], [...], [9, 10, 11, 12], [...]]

почему результат содержит [...] where проблема в цикле while

Ответ №1:

Списки являются изменяемыми объектами, поэтому ll=l=[] означает, что ll это точно такой же объект, как l . Это можно проверить с помощью is оператора:

 >>> ll is l
True
  

Это можно продемонстрировать следующим образом:

 >>> a=b=[]
>>> a
[]
>>> b
[]
>>> a.append(1)
>>> a
[1]
>>> b # For all practical purposes, a is identical to b
[1]
>>> a is b
True
  

Таким образом, строка ll.append(l) создает рекурсивный объект!
Использование pprint модуля после запуска приведенного выше кода четко указывает на это:

 >>> # Run the posted code
>>> import pprint
>>> pprint.pprint(ll)
[[1, 2, 3, 4],
 <Recursion on list with id=2032187430600>,
 [5, 6, 7, 8],
 <Recursion on list with id=2032187430600>,
 [9, 10, 11, 12],
 <Recursion on list with id=2032187430600>]
  

ll Список на самом деле не нужен, поскольку l.append метод уже
добавляет вновь созданный список к l объекту и создает 2D-список:

 >>> q=[[1,2,3,4]]
>>> q.append([5,6,7,8])
>>> q
[[1, 2, 3, 4], [5, 6, 7, 8]]
  

Код можно переписать следующим образом:

 a = [1,2,3,4,5,6,7,8,9,10,11,12]
l = list()
f,k = 0,4

# range(1,4) iterates m through the values [1, 2, 3]
# This includes the first but excludes the last
for m in range(1,4):

    # f and k are already integers, so no need for typecasting
    # This append statement will append the 1D slice as a single unit
    l.append(a[f:k])
    # a  = 1 is the same as a = a   1 but is more compact
    f  = 4
    k  = 4

print(l)
# Will be [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
  

Если вам действительно нужно создать два отдельных пустых списка, лучше сделать это таким образом:

 >>> q=list()
>>> w=list()
>>> q is w
False