Posts: 15
Threads: 6
Joined: Mar 2026
When I reserve space for a 2-dimensional list using [...]*n, the behaviour is different from reserving the space by explicitly filling the list.
Program fragments:
>>>a = [[0]*4]*4
>>>a
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>>for i in range(4):
... for j in range(4):
... a[i][j] = i*4+j
>>>a
[[12, 13, 14, 15], [12, 13, 14, 15], [12, 13, 14, 15], [12, 13, 14, 15]] # not what I wanted
---------------------------------------------------------------------------
>>>a = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>>for i in range(4):
... for j in range(4):
... a[i][j] = i*4+j
>>>a
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]] # this is what I wanted Is the behaviour of the first fragment documented somewhere, in other words have I missed some warning?
Posts: 1,602
Threads: 3
Joined: Mar 2020
https://docs.python.org/3/faq/programmin...nge-list-x
[[0]*4]*4 Creates one list with four elements of the number 0, but then it creates a list that original list referenced four times (not the same as 4 different lists).
Posts: 15
Threads: 6
Joined: Mar 2026
Mar-28-2026, 07:05 PM
(This post was last modified: Mar-28-2026, 07:05 PM by meijeru.)
Thanks for the explanation. I suspected as much. The question remains: how do I succinctly create a 2-dimensional list of elements that are all distinct, given that [[0]*4]*4 does not do the trick. With 4x4 the explicit way is stil manageable, but with 100x100 I could not do that. I see one way, namely using .append, but is there any other, more Pythonesque way?
Posts: 15
Threads: 6
Joined: Mar 2026
Meanwhile I found an approach in the FAQ you referenced.
Posts: 2,198
Threads: 12
Joined: May 2017
def matrix_2d(x, y):
matrix = []
for _ in range(x):
matrix.append([0] * y)
return matrix
# as list comprehension
def matrix_2d(x, y):
return [[0] * y for _ in range(x)]A generic approach which creates a matrix with n dimensions:
def create_nd_list_iterative(*dimensions, fill_value=0):
if not dimensions:
return fill_value
result = fill_value
for dim in reversed(dimensions):
result = [fill_value if not isinstance(result, list) else [x for x in result] for _ in range(dim)]
return resultOr you just use numpy, which is made for this:
import numpy as np
matrix = np.zeros((2,2,3), dtype=np.int32) The limitation here is, that you could use only one datatype in the matrix. Numpy is optimized for speed and memory.
So depending on what you want to do, you could choose. With numpy you get for free matrix multiplication, broadcast and much more.
Posts: 1,301
Threads: 151
Joined: Jul 2017
Mar-29-2026, 04:33 AM
(This post was last modified: Mar-29-2026, 04:33 AM by Pedroski55.)
The Python is lazy! It will just reference your first list, unless you force it not to! Check the ids!
a = [[0]*4]*4 # =[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
for b in a:
print(id(b))Gives:
Output: 131044815246720
131044815246720
131044815246720
131044815246720
Alter the lists:
for i in range(4):
print('***************')
for j in range(4):
a[i][j] = i*4+j
print(f'i = {i}, j = {j}, i*4+j = {i*4+j}, a[i][j] = {a[i][j]}')
# still all same id and the same list, 4 times
for b in a:
print(id(b))Start like this, without getting complicated:
a = [[0, 0, 0, 0] for i in range(4)]
# now you have 4 lists and 4 ids
for b in a:
print(id(b))Gives:
Output: 131044815246272
131044815245504
131044815314624
131044815452352
Posts: 8,204
Threads: 162
Joined: Sep 2016
Posts: 15
Threads: 6
Joined: Mar 2026
Thanks for all the replies and especially the references. Coming from Rebol/Red I should not have been surprised really.
|