Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 元素(数组)";“乘法”;vs.列表理解初始化_Python_Arrays - Fatal编程技术网

Python 元素(数组)";“乘法”;vs.列表理解初始化

Python 元素(数组)";“乘法”;vs.列表理解初始化,python,arrays,Python,Arrays,关于这个问题: 在处理二维数组时,我发现以某种方式初始化它会产生意想不到的结果。我想了解以以下两种方式初始化8x8栅格之间的区别: >>> a = [[1]*8]*8 >>> a [[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, 1, 1, 1, 1], \ [1, 1, 1, 1, 1, 1, 1, 1], [1,

关于这个问题:

在处理二维数组时,我发现以某种方式初始化它会产生意想不到的结果。我想了解以以下两种方式初始化8x8栅格之间的区别:

>>> a =  [[1]*8]*8
>>> a
[[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, 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], [1, 1, 1, 1, 1, 1, 1, 1]]
vs

意外的结果是,使用索引[0-6][x]访问的任何元素都将指向[7][x]中的最后一行。这些数组在解释器中看起来完全相同,因此我感到困惑。第一种方法有什么问题


如果相关,这些数组保存对表示棋盘正方形的GTK事件框的引用。将初始化方法更改为列表理解方法后,方块将正确响应预期的悬停和单击事件

在第一个版本中,您将创建一个包含数字1的列表,并将其乘以8次,创建一个包含8个1的列表,然后使用该列表8次来创建
a


因此,当您在第一个版本中更改任何内容时,您将在其他地方看到该更改。您的问题是您正在重用同一个实例,这在第二个版本中不会发生。

当您使用
a=[[1]*8]*8
创建2D数组时,*操作符会创建对同一对象的8个引用。因此,
[1]*8
意味着创建一个大小为8的数组,其中所有8个元素都是相同的对象(相同的引用)。由于所有元素都是相同的引用,因此更新该引用点将更改数组中每个元素的值


使用列表理解
A=[[1表示范围(8)中的i]表示范围(8)]
确保二维数组中的每个元素都是唯一引用的。这避免了您看到的所有元素同时更新的错误行为。

也许重构的第一种方法更容易理解:

one_item = [1]
row = one_item*8
matrix = row*8
如您所见,数组的数组有八个对行的引用,这意味着

(a[0] is a[1]) and (a[1] is a[2]) ...
请尝试以下示例:

a = [[1]*8]*8
a[0][0] = 2

b = [[1 for i in range(8)] for j in range(8)]
b[0][0] = 3

print a
print b

print (a[0] is a[1]) and (a[1] is a[2]) and (a[2] is a[3]) # true

print (b[0] is b[1]) and (b[1] is b[2]) and (b[2] is b[3]) # false

我怀疑这可能已经被问到和回答了。我应该看起来更好…因为
[1]
包含一个不可变的,你可以使用
[[1]*8 for uuuuuuuuuuuuuuu8]
来生成所需的结果。@MartijnPieters但是假设
a=[1,2]
那么
[a]*5
[a for uuuuuuu5]
相同。@GrijeshChauhan:是的,那是一样的;一个包含5个引用的列表,其值为
[1,2]
@GrijeshChauhan:请参见
[[1]*8,用于范围(8)]
中的j,也应起作用,因为数字是不可变的。也许列表元素是对正在更新的内部变量的引用。诚然,我不能给出示例实现的细节。然而,实际上,我可以说,列表中的所有8个索引都引用了相同的对象。我喜欢这个答案的简洁性,因为问题并不复杂。
a = [[1]*8]*8
a[0][0] = 2

b = [[1 for i in range(8)] for j in range(8)]
b[0][0] = 3

print a
print b

print (a[0] is a[1]) and (a[1] is a[2]) and (a[2] is a[3]) # true

print (b[0] is b[1]) and (b[1] is b[2]) and (b[2] is b[3]) # false