首页 > 编程语言 >Python遍历时删除元素问题(附深拷贝与浅拷贝介绍)

Python遍历时删除元素问题(附深拷贝与浅拷贝介绍)

时间:2023-04-02 11:11:26浏览次数:43  
标签:va Python print 类型 拷贝 copy id 附深

问题

有时候,我们希望用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

相关文章

  • python面向对象进阶
    面向对象进阶类型判断issubclasstypeisinstance反射反射的四个函数importlib类的其他成员__str____repr____format____del____dict__和__slots____item__系列__init____new____call____doc____iter__和__next____ente......
  • [oeasy]python0123_中文字符_文字编码_gb2312_激光照排技术_王选
    中文编码GB2312回忆上次内容上次回顾了日韩各有编码格式日本有假名五十音一字节可以勉强放下 有日本汉字字符数量超过20000+  韩国有谚文数量超过500一个字节放不下 有朝鲜汉字字符数量超过20000+......
  • Python异常 ValueError的问题详解
    导读这篇文章主要介绍了Python异常ValueError的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教Python异常ValueErrorValueError:invalidliteralforint()withbase10:'*'试图将一个与数字无关的类型转化为整数,会抛出该异常。......
  • 爬虫简单python小程序
    importrequestsfrombs4importBeautifulSoupbase_url='your_base_url_here'#根据网站的实际URL模式修改此函数defget_page_url(page_number):returnf'{base_url}?page={page_number}'#根据网站的HTML结构,您可能需要修改以下选择器以获取游戏标题defget_g......
  • python的类继承总结
    参考文档:https://blog.csdn.net/yilulvxing/article/details/85374142总结如下:第一种情况:子类和父类都有__init__(self)方法情况继承研究#如果子类也有init方法,那么调用父类的实例属性必须要在子类的init()方法中有这个super().__init__()【这点尤其要注意】#如果子类也有in......
  • Python内存管理
    Python内存管理的三个阶段:1.引用计数引用计数是Python内存管理的第一道防线。当一个对象被引用时,Python会为其分配一段内存,并将其引用计数设置为1。当对象被多次引用时,其引用计数会逐渐增加。当一个对象不再被引用时,Python将其引用计数减少1。当一个对象的引用计数变为......
  • 赋值,浅拷贝,深拷贝
    在Python中,浅拷贝、深拷贝和赋值,它们之间的区别在于它们复制对象的方式,具体可以分别如下:1.赋值(相当于对象引用)赋值只是将一个变量指向一个已存在的对象,这个变量与这个对象就共享了一个内存地址,当修改这个对象时,所有指向它的变量都会发生变化,例如:list1=[1,2,3]list2=......
  • 【转载】 解决VSCode运行或调试python文件无反应的问题
    ————————————————版权声明:本文为CSDN博主「姜行者」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/kraisi/article/details/127287966  ====================================================  ......
  • import this Python之禅 20条准则
    运行importthis这句代码后返回的内容importthisTheZenofPython,byTimPetersBeautifulisbetterthanugly.Explicitisbetterthanimplicit.Simpleisbetterthancomplex.Complexisbetterthancomplicated.Flatisbetterthannested.Sparseisbette......
  • python pygame播放音频文件
    pythonpygame播放音频文件 pipinstallpygame  importpygame#Initializepygamepygame.init()#LoadtheMP3filepygame.mixer.music.load("1.mp3")#PlaytheMP3filepygame.mixer.music.play()#WaitfortheMP3filetofinishplayingwhil......