* python中二维矩阵初始化操作

unftdfkk  于 2022-11-19  发布在  Python
关注(0)|答案(2)|浏览(197)

初始化一个二维矩阵

board = [[0] * width for _ in range(height)]

代替

board = [[0] * width] * height

因为它只创建一次列表,并且每行都引用同一个列表。
在第一种情况下,我们仍然使用*,所以每行中的每列都应该引用给定行中的相同元素。但情况并非如此,为什么?

9jyewag0

9jyewag01#

0不可变。
实际上,这并不是导致看似不同的行为的根本原因,真实的的区别在于,你不打算改变0的值(因为你不能改变),所以,如果你改变了其中一个的值(如果可能的话),你并不真正知道0的值会不会改变。
请注意,这与外部迭代相同。
第一个
在这里,您可以更改T[0]而不更改T[1]
第一次
所以,如果改变T[0][0]也不会改变T[0][1],你不应该感到惊讶。如果说T[0][0]=5仍然保持T[0][1]为2,这里没有不同的行为。
看起来不同的行为发生的地方是,您不是在更改T[0],而是在更改其内容。

T=[[0]*3]*3
T[0][0]=12
T
#[[12, 0, 0], [12, 0, 0], [12, 0, 0]]

但这不是一回事!你改变的是T[0]的内容,而不是T[0]本身。
因此,如果您想比较outer数组和内部数组的情况(这就是您的问题:为什么改变一列不会影响另一列。为什么改变T[0][0]不会影响T[0][1]),您应该与下面这样的操作进行比较

T[0][0].content=5

这是一个不改变T[0][0]但改变其内容的操作,它改变了存储在T[0][0]中的对象0的值。
如果这样的操作是可能的,那么你会看到

T=[[0]*3]*3
T[0][0].content=5
#[[5, 5, 5], [5, 5, 5], [5, 5, 5]]

但是这样的操作是不可能的。因为0是不可变的。因此你不能执行类似于改变T[0]的内容的操作。因此你不可能在两个操作之间有令人惊讶的行为差异,因为它们根本不是同一个操作。T[0][0]改变了T[0]的内容,但改变了T[0][0]本身。

简化问题

我知道前面的论证可能很难理解,因为T[0]有两个角色:它既是数组又是数组元素。
因此,简化问题可能更容易。
你的问题可以归结为4种操作(包括1种不可能的操作):

# Operation 1
T=[0]*3
T[0]=5
# T=[5,0,0]. T[1] is still 0

# Operation 2
T=[{'x':0}]*3
T[0]={'x':5}
# [{'x': 5}, {'x': 0}, {'x': 0}]

# Operation 3 (impossible)
T=[0]*3
T[0].content=5
# [5, 5, 5]

# Operation 4
T=[{'x':0}]*3
T[0]['x']=5
# [{'x': 5}, {'x': 5}, {'x': 5}]

您的问题是“为什么在操作1中只更改了一个元素,而在操作4中更改了所有元素”。
我的答案是,你在比较不同的东西。操作1(改变T[0])与操作2相似。在操作2中,也只有一个元素发生了变化。
操作4(改变T[0]的内容)与操作3类似。如果操作3是可能的。但它不是。因为整数是不可变的。如果它们不是,那么操作3将是可能的,然后你会看到,在这样的操作之后,所有的元素也会改变(即对同一元素的3个引用的所有值)
回到你的例子:更改T[0][0]只是在数组T[0]中执行的操作1,因此它不影响T[0]的其他元素是正常的。您更改的不仅仅是T[0][0]的内容。但是,从数组T的Angular 来看,更改T[0][0]也会更改T[0]的内容。这与操作4类似。因此,它会影响同一数组的其他引用,即T[1]T[2],这是正常的。

x7yiwoj4

x7yiwoj42#

请参阅List of lists changes reflected across sublists unexpectedly

In  [1]: a = object()                                                                                                           
                                                                                                                                
In  [1]: [a] * 10                                                                                                               
Out [1]:                                                                                                                        
[<object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>,                                                                                                    
 <object at 0x7f57d0670a90>]

当列表相乘时,结果列表中的对象将是具有相同id()的相同示例。因此,[0] * width(一个list)将在所有行[0..height)中共享。

相关问题