Python中的引用方法(列表构造)
问题
构造方法
'''
python 3.10.7 utf-8
Author: kai
Time: 2023-11-22
'''
def mxArrary_show(mxArray):
print(mxArray, end='\n\n')
for row in mxArray:
print(row)
print("----------------")
# 构造方法一
mxArray1 = [[0] * 5] * 5
# 构造方法二
mxArray2 = [[1 for i in range(5)]for j in range(5)]
mxArrary_show(mxArray1)
mxArrary_show(mxArray2)
mxArray1[1][1] = 2
mxArray2[1][1] = 2
mxArrary_show(mxArray1)
mxArrary_show(mxArray2)
创建的二维列表
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
----------------
[[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]
----------------
经过修改的结果
[[0, 2, 0, 0, 0], [0, 2, 0, 0, 0], [0, 2, 0, 0, 0], [0, 2, 0, 0, 0], [0, 2, 0, 0, 0]]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
----------------
[[1, 1, 1, 1, 1], [1, 2, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]][1, 1, 1, 1, 1]
[1, 2, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
----------------
问题
为何存在
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
[0, 2, 0, 0, 0]
和
[1, 1, 1, 1, 1]
[1, 2, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
的修改差异。在对第[1][1]个元素进行修改的时候,mxArray[1]全都进行了更改。
原因
当创建“[0]*5”时,它确实看起来像是多次引用同一个列表,但事实并非如此。
inner_list=[0]*5
这里,“inner_list”是一个包含五个元素的列表,所有元素都是整数“0”,这创建对同一列表"[0]"的引用,它是在创建一个包含 5 个相同引用的列表,而不是创建 5 个独立的列表;最后,它创建了一个包含五个[0](列表内容为一个0)的新列表(inner_list)。
现在,在嵌套列表中使用此选项时:
outer_list=[inner_list]*5
实际上,它就是重复了对同一列表对象的引用。因此,如果您修改“inner_list”的内容(例如,“inner_list[1]=42’”),您将看到“outer_list”所有元素中都反映了更改。
简言之,“[0]*5”创建一个具有五个零的新列表,而“[inner_list]*5’创建一个带有对同一列表的五个引用的列表(“inner_list”)。
问题举例
inner_list = [0]
outer_list = inner_list * 5
print(outer_list) # 输出 [0, 0, 0, 0, 0]
outer_list[1] = 2
print(outer_list) # 输出 [0, 2, 0, 0, 0]
在这个问题中"outer_list[1] = 2"其实是修改了outer_list[1]的值,使其为2
而不是最开始引用的"inner_list".
这样子更好说明:
inner_list = [0]
outer_list = inner_list * 5
print(outer_list)
for row in outer_list:
print(id(row))
'''
输出:
[0, 0, 0, 0, 0]
1814176465104
1814176465104
1814176465104
1814176465104
1814176465104
'''
outer_list[1] = 2
print(outer_list)
for row in outer_list:
print(id(rowv))
'''
输出:
[0, 2, 0, 0, 0]
1814176465104
1814176465168 <
1814176465104
1814176465104
1814176465104
'''
在"outer_list[1] = 2"之后,outer_list[1]位置的id发生了变化,而outer_list其他元素仍然使用相同id(相同inner_list对象)
回到二维数组
inner_list = [0] * 5
outer_list = [inner_list] * 5
'''
outer_list = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
'''
outer_list[1][1] = 1
'''
outer_list = [[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
'''
"outer_list[1][1] = 1"是对outer_list\[1][1]也就是inner_list(outer_list\[1])的inner_list[1]的修改,而outer_list是由 5个 相同的inner_list组成,因此 outer_list的5个元素都会发生相同的变化。
额外展示一下:
inner_list = [0] * 5
outer_list = [inner_list] * 5
print(outer_list)
for i in outer_list:
print(id(i))
outer_list[1][1] = 1
print(outer_list)
for i in outer_list:
print(id(i))
outer_list[1] = [2, 2, 2, 2, 2]
print(outer_list)
for i in outer_list:
print(id(i))
'''
输出结果为:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
2186803516096
2186803516096
2186803516096
2186803516096
2186803516096
[[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
2186803516096
2186803516096
2186803516096
2186803516096
2186803516096
[[0, 1, 0, 0, 0], [2, 2, 2, 2, 2], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
2186803516096
2186803515520
2186803516096
2186803516096
2186803516096
'''
各位也可以试试输出 内层列表 中元素 的id看看,内容比较多,这里就不贴出了。