为什么Python列表理解似乎与列表和“乘法”的行为不同?
出于好奇心问。为了提出一个观点,我试图制作一个函数,该函数返回n维的“身份矩阵”,然后以最简洁的方式打印它。 首先,我想出了这一点:
def identity(n):
zeros = [[0 for j in range(n)] for i in range(n)]
for i in range(n):
zeros[i][i] = 1
return zeros
for i in range(5):
print(identity(5)[i])
这是按预期的工作,但是我尝试通过这样做将语法变短:
def identity(n):
zeros = [[0]*n]*n
for i in range(n):
zeros[i][i] = 1
return zeros
for i in range(5):
print(identity(5)[i])
出于某种原因,每个元素都会将每个元素更改为一个元素,但是我似乎无法弄清楚为什么?这不是一个重要的问题,但要感谢您的帮助!
Asking out of curiosity. For the sake of making a point I was trying to make a function that returns an "identity matrix" of n dimensions and then printing it in the most concise way.
First I came up with this:
def identity(n):
zeros = [[0 for j in range(n)] for i in range(n)]
for i in range(n):
zeros[i][i] = 1
return zeros
for i in range(5):
print(identity(5)[i])
This works as intended, however then I tried making the syntax shorter by doing this:
def identity(n):
zeros = [[0]*n]*n
for i in range(n):
zeros[i][i] = 1
return zeros
for i in range(5):
print(identity(5)[i])
And this for some reason changes every single element to a one, but I can't seem to figure out why?. This isn't an important question but help is much appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是因为列表理解在元素上执行浅副本。
Zeros
中的所有元素都参考同一列表。尝试这些并查看结果:
您可以了解有关浅层和深拷贝。
It's because list comprehension performs shallow copy on the element.
All elements in
zeros
are refering to the same list.Try these and see the results:
You can learn more about difference between shallow and deep copy here.
这是因为当您将列表乘以一个数字时,它会复制它,但是它通过复制每个元素的引用来做到这一点。
如果您执行
ID(ZEROS [0] [0])
和ID(ZEROS [0] [1])
对于第二种情况,您将看到它们是同样,即它们指的是相同的元素,并修改一个元素会修改所有内容。对于第一种情况,每个0分开实例化并且具有自己的ID并不是这样。
编辑:
This is because when you multiply a list with a number, it duplicates it, but it does so by copying the reference of each element.
If you do
id(zeros[0][0])
andid(zeros[0][1])
for the second case, you will see that they are the same, i.e. they refer to the same element and modifying one modifies them all.This is not true for the first case where every 0 is instantiated seperately and has its own id.
Edit:
列表由Python中的参考保存。
这意味着,如果您有:
list_a和list_b实际上指向内存中的同一对象。因此,如果您更改list_a的元素:
那么list_b的相同元素将更改,因为它们指向同一对象。 IE list_a实际上以各种方式等于list_b。
这也是您代码中发生的事情。
当您遍历每个值并分配每个值时,就好像您明确创建了一个新列表并将其分配给外表列表的每个元素:
但是在第二件代码中,好像您在重复附加相同的值列表:
lists are kept by reference in python.
This means that if you have:
list_a and list_b are actually pointing to the same object in memory. so if you change an element of list_a:
then the same element for list_b will change because they are pointing to the same object. i.e. list_a literally equals list_b in every way.
That's what's happening in your code as well.
When you loop through and assign each value then it's as if you were explicitly creating a new list and assigning it to each element of your outter list:
but in the second piece of code, it is as if you are repeatedly appending the same value to the list: