一段關於Python字典遍曆的“爭論”

來源:互聯網
上載者:User
轉:http://ihipop.info/2010/10/1777.html
Python代碼
  1. #這裡初始化一個dict   
  2. >>> d = {'a':1, 'b':0, 'c':1, 'd':0}   
  3. #本意是遍曆dict,發現元素的值是0的話,就刪掉   
  4. >>> for k in d:   
  5. ...   if d[k] == 0:   
  6. ...     del(d[k])   
  7. ...   
  8. Traceback (most recent call last):   
  9.   File "<stdin>", line 1, in <module>   
  10. RuntimeError: dictionary changed size during iteration   
  11. #結果拋出異常了,兩個0的元素,也只刪掉一個。   
  12. >>> d   
  13. {'a': 1, 'c': 1, 'd': 0}   
  14.     
  15. >>> d = {'a':1, 'b':0, 'c':1, 'd':0}   
  16. #d.keys() 是一個下標的數組   
  17. >>> d.keys()   
  18. ['a', 'c', 'b', 'd']   
  19. #這樣遍曆,就沒問題了,因為其實其實這裡遍曆的是d.keys()這個list常量。   
  20. >>> for k in d.keys():   
  21. ...   if d[k] == 0:   
  22. ...     del(d[k])   
  23. ...   
  24. >>> d   
  25. {'a': 1, 'c': 1}   
  26. #結果也是對的   
  27. >>>  

 

其實這個問題本來很簡單,就是說如果遍曆一個字典,但是在遍曆中改變了他,比如增刪某個元素,就會導致遍曆退出,並且拋出一個dictionary changed size during iteration的異常
bones的解決方案是遍曆字典索引值,以字典索引值為依據遍曆,這樣改變了value以後不會影響遍曆繼續。
但是下面又有一位大神拋出高論:

首先,python 是推薦使用迭代器的,也就是 for k in adict 形式。其次,在遍曆中刪除容器中的元素,在 C++ STL 和 Python 等庫中,都是不推薦的,因為這種情況往往說明了你的設計方案有問題,所有都有特殊要求,對應到 python 中,就是要使用 adict.key() 做一個拷貝。最後,所有的 Python 容器都不承諾安全執行緒,你要多線程做這件事,本身就必須得加鎖,這也說明了業務代碼設計有問題的

 

但由“遍曆中刪除特定元素”這種特例,得出“遍曆dict的時候,養成使用 for k in d.keys() 的習慣”,我覺得有必要糾正一下。在普通的遍曆中,應該使用 for k in adict。
另外,對於“遍曆中刪除元素”這種需求,pythonic 的做法是 adict = {k, v for adict.iteritems() if v != 0} 或 alist = [i for i in alist if i != 0]

 

這個寫法讓我眼前一亮:怎麼還有這個文法?
再仔細一看,他可能是這個意思:

 

Python代碼
  1. #!/usr/bin/env python   
  2. # -*- coding=utf-8 -*-   
  3. a = {'a':1, 'b':0, 'c':1, 'd':0}   
  4. b={}   
  5. for k,v in a.items():   
  6.     if v != 0:   
  7.         b.update({k:v})   
  8. adict = b   
  9. del b   
  10. print a  

不知道對不對。
因為這個寫法一開始讓我猛然想到三元操作符,仔細一看才發現不是,以前Goolge到有個解決方案

 

Python代碼
  1. val = float(raw_input("Age: "))   
  2. status = ("working","retired")[val>65]   
  3. print "You should be",status  

val>65是個邏輯運算式,返回0或者1,剛好作為前面那個元組的ID來取值,實在是太妙了。。。
不過在Google的資料裡面還有一個版本

後來發帖在華蟒使用者組(中文Python技術郵件清單)(http://groups.google.com/group/python-cn/browse_thread/thread/047b1401e96c4b88#)中提到後眾多大神解答如下:

 

Python代碼
  1. >>> alist = [1,2,0,3,0,4,5]   
  2. >>> alist = [i for i in alist if i != 0]   
  3. >>> alist   
  4.   
  5. [1, 2, 3, 4, 5]   

 

 

Python代碼
  1. >>> d = {'a':1, 'b':0, 'c':1, 'd':0}   
  2. >>> d = dict([(k,v) for k,v in d.iteritems() if v!=0])   
  3. >>> d   
  4. {'a':1,'c':1'}   

如果大於Python>=2.7
還可以用這個寫法:

 

PHP代碼
  1. >>> d = {k:v for k,v in d.iteritems() if v !=0 }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.