Python多维数组初始化的两种方式和浅拷贝问题

本文探讨了Python中使用列表初始化多维数组的两种方法:通过复制列表元素和通过循环赋值。详细对比了这两种方法的区别,特别是浅拷贝所带来的问题,并通过id函数验证了不同初始化方法下列表对象的内存地址差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python提供了列表、元组、字典等数据结构,列表可以进行多层嵌套,形成“多维数组”。
最近在Python中使用列表嵌套定义数组时遇到了浅拷贝的问题,对多维数组初始化的2种方法进行了总结。

1.[0]*n复制列表

  使用列表元素相乘的方式 [[[0]*a]*b]*n,初始化元素值为0的n维a*b数组。假设a=3,b=4,n=2,其初始化原理是将列表[0]复制3次成为[0,0,0],再将[0,0,0]列表对象的引用复制4次,得到初始化后的2维数组。
  值得注意的是,把[0,0,0]*4这种复制形式是一种浅拷贝。对于list中的元素,浅拷贝就只会使用原始元素的引用(内存地址),也就是说A[0][1]、A[1][1]、A[2][1]、A[3][1]对应的是同一个内存地址,当对A中元素A[0][1]进行修改时,对象A中的A[i][1]的值都会发生变化。

# 初始化一维list
A=[0]*4
A
[0, 0, 0, 0]
# 改变其中一个元素的值
A[0]=1
A
[1, 0, 0, 0] #不影响列表中其他元素的值

# 初始化一个2维的4×3的数组,嵌套的list
A=[[0]*3]*4
A
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
#改变数组中的元素的值
#嵌套列表初始化之后,内层列表元素值的改变,会影响整个列表对象A的值
A[0][1]=1
A
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
A[1][1]=0
A
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

2.通过循环赋初始值

通过for循环对列表进行赋值,逐个初始化元素为0。这种情况不会出现方法1中出现的浅拷贝问题。

B=[[0 for t in range(2)]for i in range(3)]
B
[[0, 0], [0, 0], [0, 0]]
B[0][1]=1
B
[[0, 1], [0, 0], [0, 0]]

综上所述,通过循环赋初始值是一种比较推荐的初始化方法,不会因为对象引用的问题产生bug。
关于赋值、浅拷贝、深拷贝,可以用id()函数做实验,深入理解。id()函数可以返回对象的唯一编号,代表对象在python解释器中的内存地址。具体可参见这篇博客图解 Python 深拷贝和浅拷贝

# 方式1
A=[0]*4
print id(A)
A=[[0]*3]*4
print id(A)
A[0][1]=1
print id(A[0]),id(A[1])
# 方式2
B =[[0 for i in range(3)]for j in range(2)]
print id(B[0]),id(B[1])

结果

# 方式1 列表内部的列表具有相同id,由此产生浅拷贝问题
210971272 # id [0]*4
138267400 # id [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
138267208 138267208  #id(A[0]),id(A[1])
# 方式2 嵌套列表内部的列表具有不同的id
210971720 210871240
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值