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中的多进程与多线程的使用
Apr 07 Python
Python用threading实现多线程详解
Feb 03 Python
python3中dict(字典)的使用方法示例
Mar 22 Python
浅谈django model的get和filter方法的区别(必看篇)
May 23 Python
PyQt 线程类 QThread使用详解
Jul 16 Python
Python有序字典简单实现方法示例
Sep 28 Python
python分批定量读取文件内容,输出到不同文件中的方法
Dec 08 Python
python读写csv文件方法详细总结
Jul 05 Python
python操作excel让工作自动化
Aug 09 Python
在Python中利用pickle保存变量的实例
Dec 30 Python
在Keras中CNN联合LSTM进行分类实例
Jun 29 Python
基于Python的图像阈值化分割(迭代法)
Nov 20 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中可以自动分割查询字符的Parse_str函数使用示例
2014/07/25 PHP
php实现读取手机客户端浏览器的类
2015/01/09 PHP
教大家制作简单的php日历
2015/11/17 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
2016/07/02 PHP
php实现的网页版剪刀石头布游戏示例
2016/11/25 PHP
Javascript typeof 用法
2008/12/28 Javascript
JavaScript中的console.dir()函数介绍
2014/12/29 Javascript
使用JQuery FancyBox插件实现图片展示特效
2015/11/16 Javascript
简单谈谈gulp-changed插件
2017/02/21 Javascript
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
bootstrap 路径导航 分页 进度条的实例代码
2018/08/06 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
2018/09/07 Javascript
微信小程序实现留言板功能
2018/11/02 Javascript
使用jquery模拟a标签的click事件无法实现跳转的解决
2018/12/04 jQuery
vue-week-picker实现支持按周切换的日历
2019/06/26 Javascript
vue 实现移动端键盘搜索事件监听
2019/11/06 Javascript
JavaScript实现答题评分功能页面
2020/06/24 Javascript
小程序自动化测试的示例代码
2020/08/11 Javascript
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
Python help()函数用法详解
2014/03/11 Python
python对配置文件.ini进行增删改查操作的方法示例
2017/07/28 Python
基于python时间处理方法(详解)
2017/08/14 Python
Python实现的概率分布运算操作示例
2017/08/14 Python
高效使用Python字典的清单
2018/04/04 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
2019/10/14 Python
Python 解析pymysql模块操作数据库的方法
2020/02/18 Python
python数据预处理 :数据抽样解析
2020/02/24 Python
JSF面试题:Jsf中导航的标签是什么
2013/04/20 面试题
安全标语口号
2014/06/09 职场文书
汽车服务工程专业自荐信
2014/09/02 职场文书
2014年合同管理工作总结
2014/12/02 职场文书
高中体育课教学反思
2016/02/16 职场文书
使用Redis实现秒杀功能的简单方法
2021/05/08 Redis
Vue实现动态查询规则生成组件
2021/05/27 Vue.js
Python中OpenCV实现查找轮廓的实例
2021/06/08 Python
mybatis 解决从列名到属性名的自动映射失败问题
2021/06/30 Java/Android