日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

python for循環remove同一個list過程解析

系統 1847 0

下午在用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。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 北票市| 阳泉市| 柘城县| 莱西市| 珠海市| 盐池县| 新宾| 平湖市| 五河县| 泸溪县| 桂阳县| 洪江市| 扬州市| 崇文区| 隆昌县| 宝兴县| 金坛市| 博野县| 富民县| 含山县| 浪卡子县| 随州市| 新巴尔虎右旗| 泰来县| 佛坪县| 南汇区| 海口市| 客服| 凌源市| 和龙市| 永福县| 盐源县| 巍山| 彰化市| 承德市| 探索| 视频| 义马市| 玉环县| 阳原县| 鹤峰县|