问题
有时候,我们希望用Python遍历一个列表(或其他可迭代对象),如果其中有我们不需要的元素就把它删除并继续遍历。
如以下代码段,我们本希望打印1、3
,可最后却只打印了1
。
a = [1,2,3]
for i in a:
if i == 2:
a.remove(i)
else:
print(i)
分析
其实,之所以会有上述问题的出现,是因为元素2
被删除后,3
到了2
的位置,导致解释器以为遍历结束,则没有继续打印3
,如下图示:
[
1, <= 打印
2,
3
]
[
1,
2, <= 触发if条件,删除
3
]
[
1,
3 <= 删除“2”后“3”到了“2”的位置,
解释器误以为没有下一个可迭代元素,
结束遍历
]
解决
为了解决上述问题,我们可以建立一个原数据的副本,使正本数据正常遍历,而删减副本中的数据,如此我们便可以同时得到遍历结果和删减后的列表了,如下代码:
import copy
a = [1,2,3]
b = copy.deepcopy(a) # 或 b = a.copy()
for i in a:
if i == 2:
b.remove(i)
else:
print(i)
print('原始数据',a,'删减后元素:',b)
输出:
1
3
原始数据 [1, 2, 3] 删减后元素: [1, 3]
扩展
您可能会注意到,以下解法是错误的,其还是只会打印1
:
a = [1,2,3]
b = a
for i in a:
if i == 2:
b.remove(i)
else:
print(i)
其实,上述的“赋值”操作其实就是传递了对象的引用(即在内存中的位置),a和b实际指向的是同一个列表。
我们可以用id
函数来证实这一点:
import copy
va = [1,2,3]
vb = va
vc = copy.deepcopy(va)
vd = va.copy()
print(id(va), id(vb), id(vc), id(vd))
结果:2336177198528 2336177198528 2336177114176 2336177226432
我们可以看到,va和vb的id是相同的,而它们与vc、vd的id却是不同的。这是因为深拷贝后程序会新开辟一块内存空间,并把原来的数据复制过去。此时,改变vc、vd的值就和va没有关系了。
- 会使用浅拷贝的数据类型:list类型(列表类型)、set类型(数组类型)、dict类型(列表类型)
- 不会使用浅拷贝的数据类型:str类型(字符串类型)、int类型(整数类型)、float类型(浮点数类型)、complex类型(复数类型)、tuple类型(元组类型)
除了用copy库的deepcopy方法以外,会使用浅拷贝的数据类型一般还内置了copy方法,如下:
# 列表
la = [1,2,3]
lb = la.copy()
# 集合
sa = {1,2,3}
sb = sa.copy()
# 字典
da = {1:1,2:2,3:3}
db = da.copy()
其也可以起到和copy.deepcopy相同的作用。
标签:va,Python,print,类型,拷贝,copy,id,附深 From: https://www.cnblogs.com/XuShuo-Self/p/17280088.html