这两种方式中的怪异行为可创建多维列表[重复]

问题描述 投票:1回答:1

我已经尝试使用两种不同的方法在Python 3.7中创建多维列表。但是他们的行为有所不同,我感到困惑。

我已经尝试创建8 * 2 * 1 * 29多维数组。第一个是使用复制,如下所示:

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

第二个重复:

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)]

当我将值分配给某个位置时,似乎它们以第一种方式被复制8次,而在第二种版本中则没有。我的问题在于,很难理解为什么创建副本以及为什么仅在第一维创建副本。

例如,如果我设置了

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

我得到的第一个版本的结果是:

[[[[-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]]]]

感谢您的帮助。

python python-3.x
1个回答
1
投票

发生的情况是,在第一种技术中,内部列表作为外部列表中的元素被共享。换句话说,所有列表元素实际上都指向相同的数据值。

为简单起见,我们有这个:

table1 = [[0] * 4] * 4

这实际上等效于此分解版本:

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

输出:

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

[row,
 row,
 row,
 row]

因此,该表中的所有行实际上都是相同的数据,执行table[0][0] = 1等同于执行row[0] = 1,因此修改了所有行。

列表理解不会发生这种情况的原因是它正在创建新行:

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

这等效于此展开的版本:

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

table2 = [row1,
          row2,
          row3,
          row4]

因此评估table2[0][0] = 1仅修改row1

...为什么只在第一维。

它实际上在各处创建了副本:

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]]]
© www.soinside.com 2019 - 2024. All rights reserved.