1

I have tried to create a multi-dimension list in Python 3.7 using two different ways. But they behave differently and I got confused.

I have tried to create an 8*2*1*29 multi-dimension array. The first one is to use duplicating as below:

arrayToCreate = [[[[-1]* 29]*1] *2] *8

The second one by repeating:

arrayToCreate = [[[[-1 for x in range(0,29)] for y in range(0,1)] for x in range(0,2)] for t in range(0,8)]

When I assign a value to some location, it seems that they are copied 8 times in the first way but no in the second version. The problem for me is that it is hard to understand why it creates copies and why only in the first dimension.

For example, if I set

arrayToCreate[0][0][0][3]= 4445

The result I got for the first version is:

[[[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]],
 [[[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]],
  [[-1, -1, -1, 4445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]]]]

Thanks for your help.

ROpdebee
  • 249
  • 1
  • 7

1 Answers1

1

What's happening is that the inner lists are being shared as the elements in the outer list in the first technique. In other words, all of the list elements actually point to the same data value.

To simplify, let's say we have this:

table1 = [[0] * 4] * 4

This is actually equivalent to this decomposed version:

row = [0] * 4
table1 = row * 4

Output:

[[0, 0, 0, 0],
 [0, 0, 0, 0],
 [0, 0, 0, 0],
 [0, 0, 0, 0]]

or

[row,
 row,
 row,
 row]

Thus, all rows in this table are actually the same data, and doing table[0][0] = 1 would be equivalent to doing row[0] = 1, hence modying all rows.

The reason this doesn't happen with list comprehensions is that it is creating new rows:

table2 = [[0 for _ in range(4)] for _ in range(4)]

This is equivalent to this unrolled version:

table2 = [[0 for _ in range(4)],
          [0 for _ in range(4)],
          [0 for _ in range(4)],
          [0 for _ in range(4)]]

Or

table2 = [row1,
          row2,
          row3,
          row4]

Thus evaluating table2[0][0] = 1 only modifies row1.

... why only in the first dimension.

It actually creates copies everywhere:

table3 = [[[0] * 2] * 2] * 2

# Set the first element of every innermost list
table3[0][0][0] = 1
# [[[1, 0], [1, 0]],
#  [[1, 0], [1, 0]]]

# Set the first innermost list itself in its "parent" list
table3[0][0] = 1
# [[1, [1, 0]],
#  [1, [1, 0]]]
ROpdebee
  • 249
  • 1
  • 7
  • Thank you ROpdebee for your great answer. It definitely clears my confusion. Also thanks juanpa.arrivillag abd user2357112 for referring me to a duplicated question. – icemountain Oct 28 '19 at 06:05