python for循环remove同一个list过程解析


Posted in Python onAugust 14, 2019

下午在用python将Linux的conf配置文件转化成字典dict时遇到了一个奇怪的问题,原先conf配置文件中没有注释行(以#开头的行),后来为了避免这种情况,添加了一个对以#开头的行删除的操作。 实践结果颠覆了已有的认知,直接上代码示例。

代码片段1

#!/usr/bin/python 
# encoding: utf-8  
# -*- coding: utf8 -*-  
import re  
list_to_test = ['# ', '# conf', 'NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']  
for member in list_to_test:  
 if re.search('^#+.*', member) is not None:  
  list_to_test.remove(member)  
print list_to_test

结果1:

['# conf', 'NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']

代码片段2

#!/usr/bin/python 
# encoding: utf-8  
# -*- coding: utf8 -*-  
list_to_test = ['# ', '# conf', 'NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']  
list_to_test.remove('# ')  
list_to_test.remove('# conf')  
print list_to_test

# 结果2:

['NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']

本以为上述两个代码的结果应该是一样的,结果不一样。

分析:

原因是不能在for循环中用remove同一个列表(遍历中删除)。当remove这个list中的元素时,list的长度发生了变化,for循环就会受到影响(这个python版本(2.7.x没有明显的报错,可能作者并不认为这是一个issue或bug,但给点提示也是好的啊)。

解决办法:

用一个新的列表(list)去代替循环中的list或者代替remove操作的list。在创建新的列表是可以用cpoy模块中的deepcopy方法也可以用new_list = old_list[:]的方法,如下:

#!/usr/bin/python
# encoding: utf-8
# -*- coding: utf8 -*-
import re
from copy import deepcopy

old_list = ['# ', '# conf', 'NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']
new_list = deepcopy(old_list)
for member in new_list:
 if re.search('^#+.*', member) is not None:
  old_list.remove(member)
print old_list

有趣(令人困惑)的是切片也是浅复制,但利用切片也可以实现上述功能,代码如下:

#!/usr/bin/python
# encoding: utf-8
# -*- coding: utf8 -*-
import re
old_list = ['# ', '# conf', 'NAME="Ubuntu"', 'VERSION="14.04.3 LTS, Trusty Tahr"']
new_list = old_list[:]
for member in new_list:
 if re.search('^#+.*', member) is not None:
  old_list.remove(member)
print old_list

上述导致错误发生的例子(在for循环中用remove同一个列表)可以认知为这个操作是修改对象势必影响此对象,要想修改一个对象却不影响此对象引用,则需要对象复制。如果你想修改一个对象,而且想让原始的对象不受影响,那你就需要对象复制。

附加知识点:

关于浅复制(浅拷贝)

对象的浅复制(shallow copy):它虽然复制了对象,但对于对象中的元素,依然使用引用.

(1)、使用切片[:]操作进行拷贝 (注释:切片只复制了对象的顶层,对对象的下一层还是引用,举个例子:[1,2,3,[4,5,6]])

(2)、使用工厂函数(如list/dir/set)等进行拷贝

(3)、copy.copy()

(4)、=(赋值)操作(注释:原文没有,此处是新添加的,根据“对象的赋值实际上是对象的引用”添加)

如果希望复制一个容器对象,以及它里面的所有元素(包含元素的子元素),使用copy.deepcopy这个方法会消耗一些时间和空间。不过,如果你需要完全复制,这是唯一的方法。

注意:

1、对于非容器类型(如数字、字符串、和其他‘原子'类型的对象)没有被拷贝一说。

2、如果元组变量只包含原子类型对象,则不能深copy。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python进阶教程之函数参数的多种传递方法
Aug 30 Python
python黑魔法之编码转换
Jan 25 Python
Python实现FTP上传文件或文件夹实例(递归)
Jan 16 Python
基于Python数据可视化利器Matplotlib,绘图入门篇,Pyplot详解
Oct 13 Python
利用Python如何生成便签图片详解
Jul 09 Python
Python设计模式之简单工厂模式实例详解
Jan 22 Python
Django 中自定义 Admin 样式与功能的实现方法
Jul 04 Python
用Python实现BP神经网络(附代码)
Jul 10 Python
Numpy 理解ndarray对象的示例代码
Apr 03 Python
哪些是python中web开发框架
Jun 17 Python
pycharm实现猜数游戏
Dec 07 Python
matplotlib之pyplot模块实现添加子图subplot的使用
Apr 25 Python
如何用Python来理一理红楼梦里的那些关系
Aug 14 #Python
django之自定义软删除Model的方法
Aug 14 #Python
python实现登录密码重置简易操作代码
Aug 14 #Python
python 定时器每天就执行一次的实现代码
Aug 14 #Python
Django 项目重命名的实现步骤解析
Aug 14 #Python
Django如何实现网站注册用户邮箱验证功能
Aug 14 #Python
python 叠加等边三角形的绘制的实现
Aug 14 #Python
You might like
PHP出错界面
2006/10/09 PHP
PHP 中的批处理的实现
2007/06/14 PHP
php curl模拟post请求和提交多维数组的示例代码
2015/11/19 PHP
PHP filter_var() 函数, 验证判断EMAIL,URL等
2021/03/09 PHP
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
JavaScript 比较时间大小的代码
2010/04/24 Javascript
Asp.net下使用Jquery Ajax传送和接收DataTable的代码
2010/09/12 Javascript
sencha ext js 6 快速入门(必看)
2016/06/01 Javascript
jquery 实现回车登录详解及实例代码
2016/10/23 Javascript
JS正则RegExp.test()使用注意事项(不具有重复性)
2016/12/28 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
2017/06/08 Javascript
浅谈在koa2中实现页面渲染的全局数据
2017/10/09 Javascript
关于 angularJS的一些用法
2017/11/29 Javascript
Webpack打包字体font-awesome的方法示例
2018/04/26 Javascript
Vue CLI2升级至Vue CLI3的方法步骤
2019/05/20 Javascript
Layui 数据表格批量删除和多条件搜索的实例
2019/09/04 Javascript
vuex存储复杂参数(如对象数组等)刷新数据丢失的解决方法
2019/11/05 Javascript
[02:38]DOTA2亚洲邀请赛 IG战队巡礼
2015/02/03 DOTA
[57:59]EG vs Secret 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
浅析Python中else语句块的使用技巧
2016/06/16 Python
Python列表和元组的定义与使用操作示例
2017/07/26 Python
浅谈Python里面小数点精度的控制
2018/07/16 Python
Python简单基础小程序的实例代码
2019/04/28 Python
Django实现微信小程序的登录验证功能并维护登录态
2019/07/04 Python
django 基于中间件实现限制ip频繁访问过程详解
2019/07/30 Python
python利用datetime模块计算程序运行时间问题
2020/02/20 Python
举例详解CSS3中的Transition
2015/07/15 HTML / CSS
HTML5新标签兼容——> 的两种方法
2018/09/12 HTML / CSS
联想德国官网:Lenovo Germany
2018/07/04 全球购物
美国摩托车头盔、零件、齿轮及配件商店:Cycle Gear
2019/06/12 全球购物
奥地利智能家居和智能生活网上商店:tink.at
2019/10/07 全球购物
音乐学院硕士生的自我评价分享
2013/11/01 职场文书
教室布置标语
2014/06/26 职场文书
竞聘自述材料
2014/08/25 职场文书
12.4法制宣传日活动总结
2014/08/26 职场文书
图文详解nginx日志切割的实现
2022/01/18 Servers