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统计日志中每个IP出现次数的方法
Jul 06 Python
shelve  用来持久化任意的Python对象实例代码
Oct 12 Python
Python面向对象特殊成员
Apr 24 Python
Python命名空间的本质和加载顺序
Dec 17 Python
python创造虚拟环境方法总结
Mar 04 Python
通过python实现弹窗广告拦截过程详解
Jul 10 Python
python2和python3实现在图片上加汉字的方法
Aug 22 Python
Python二次规划和线性规划使用实例
Dec 09 Python
Python线程协作threading.Condition实现过程解析
Mar 12 Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 Python
Win10下用Anaconda安装TensorFlow(图文教程)
Jun 18 Python
python数据类型强制转换实例详解
Jun 22 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
SONY ICF-F10中波修复记
2021/03/02 无线电
PHP程序员面试 切忌急功近利(更需要注重以后的发展)
2010/09/01 PHP
Drupal 添加模块出现莫名其妙的错误的解决方法(往往出现在模块较多时)
2011/04/18 PHP
php输入流php://input使用示例(php发送图片流到服务器)
2013/12/25 PHP
PHP程序员必须知道的两种日志实例分析
2020/05/14 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
JavaScript经典效果集锦
2010/07/06 Javascript
javascript 事件处理、鼠标拖动效果实现方法详解
2012/05/11 Javascript
js sort 二维数组排序的用法小结
2014/01/24 Javascript
使用CSS样式position:fixed水平滚动的方法
2014/02/19 Javascript
javascript制作的cookie封装及使用指南
2015/01/02 Javascript
手机端转盘抽奖代码分享
2015/09/10 Javascript
jQuery EasyUI封装简化操作
2016/09/18 Javascript
使用D3.js+Vue实现一个简单的柱形图
2018/08/05 Javascript
对angular4子路由&辅助路由详解
2018/10/09 Javascript
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
2018/11/14 Javascript
微信小程序自定义顶部组件customHeader的示例代码
2020/06/03 Javascript
详解React 元素渲染
2020/07/07 Javascript
微信小程序实现电子签名功能
2020/07/29 Javascript
JS实现可以用键盘方向键控制的动画
2020/12/11 Javascript
[01:14:35]DOTA2上海特级锦标赛B组资格赛#1 Alliance VS Fnatic第一局
2016/02/26 DOTA
Python回调函数用法实例详解
2015/07/02 Python
Collatz 序列、逗号代码、字符图网格实例
2017/06/22 Python
python实现简单银行管理系统
2019/10/25 Python
Django模板获取field的verbose_name实例
2020/05/19 Python
Scrapy 配置动态代理IP的实现
2020/09/28 Python
Spy++的使用方法及下载教程
2021/01/29 Python
可持续木材、生态和铝制太阳镜:Proof Eyewear
2019/07/24 全球购物
普师专业个人自荐信范文
2013/11/26 职场文书
酒吧副总经理岗位职责
2013/12/10 职场文书
幼儿园保教管理制度
2014/02/03 职场文书
业务员的岗位职责
2014/03/15 职场文书
优秀大学生自荐信
2014/06/09 职场文书
企业整改报告范文
2014/11/08 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
大学生安全教育心得体会
2016/01/15 职场文书