Python Forum
Curious behavious of pre-filled 2-dimensional list
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Curious behavious of pre-filled 2-dimensional list
#1
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?
Reply
#2
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).
Reply
#3
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?
Reply
#4
Meanwhile I found an approach in the FAQ you referenced.
Reply
#5
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 result
Or 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.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#6
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
Reply
#7
List of lists changes reflected across sublists unexpectedly
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
Thanks for all the replies and especially the references. Coming from Rebol/Red I should not have been surprised really.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Curious about decorator syntax rjdegraff42 14 6,722 May-03-2023, 01:21 PM
Last Post: rjdegraff42
  How to quantize a 4 dimensional array? PythonNPC 2 3,429 Apr-23-2022, 04:34 PM
Last Post: Gribouillis
  How to create 2 dimensional variables in Python? plumberpy 5 4,234 Mar-31-2022, 03:15 AM
Last Post: plumberpy
  Find last filled column in openpyxl Irv1n 2 20,433 Jan-16-2022, 11:05 AM
Last Post: Pedroski55
  Slicing a 2 dimensional array Scott 2 2,944 Jan-12-2022, 07:18 AM
Last Post: paul18fr
  Making a hotel filled with people categorizing them lucasrohr 3 2,857 Jan-09-2022, 05:13 PM
Last Post: lucasrohr
  Problem using two-dimensional interpolation. Result looks bad player1682 4 4,837 Oct-12-2021, 09:27 AM
Last Post: player1682
  Index data must be 1-dimensional : Classifier with sklearn Salma 0 6,927 Apr-01-2021, 03:22 PM
Last Post: Salma
  2 Dimensional Arrays Prithak 4 4,443 Mar-21-2021, 09:35 PM
Last Post: deanhystad
  comparing 2 dimensional list glennford49 10 6,816 Mar-24-2020, 05:23 PM
Last Post: saikiran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020