2009-05-29 27 views

回答

39

如果你看一看PEP234定義迭代器,它說:

1. An object can be iterated over with "for" if it implements 
    __iter__() or __getitem__(). 

2. An object can function as an iterator if it implements next(). 
3

因爲cb[0]cb.__getitem__(0)相同。請參閱python documentation

+1

True,但__getitem __()與__iter __()不同。 – grieve 2009-05-29 15:27:31

5

特殊方法如__getitem__爲對象添加特殊行爲,包括迭代。

http://docs.python.org/reference/datamodel.html#object.getitem

「for循環預計的IndexError將引發非法索引,以允許序列的末端的正確檢測。」

提高IndexError以指示序列的結束。

您的代碼基本上等同於:

i = 0 
while True: 
    try: 
     yield object[i] 
     i += 1 
    except IndexError: 
     break 

object是你迭代的for循環的東西。

47

迭代對__getitem__支持可以看作是其允許平滑的過渡時PEP234介紹iterability爲主要概念的「傳統特色」。它只適用於沒有__iter__的類,其__getitem__接受整數0,1,& c,並且一旦索引變得太高(如果有的話)就引發IndexError,典型地,在__iter__之前編碼的典型「序列」類(儘管沒有阻止你編碼新的類這也是)。個人而言,我寧願不在新代碼中依賴這個,雖然它並沒有被廢棄,也沒有消失(在Python 3中也能正常工作),所以這只是一個風格和品味的問題(「顯式更好而不是隱含的「,所以我寧願明確地支持迭代,而不是依靠__getitem__支持它隱含地爲我 - 但不是一個bigge)。

+0

當`__getitem__`被引入創建迭代器時,是否在考慮了`[]`屬性訪問的情況下完成?從閱讀答案看來,如果你想`````````訪問_和_一個迭代,你不能只使用`__getitem__`來完成。你應該使用`__getitem__`來訪問``]`和`__iter__`,對嗎? – lmichelbacher 2012-08-11 23:04:01

+0

@lmichelbacher:當然你可以看到FogleBird的回答 – kriss 2013-09-06 14:10:23

19

__getitem__早於迭代器協議,並且在過去的只有方式使事情迭代。因此,它仍然是一種迭代方法。本質上,用於迭代的協議是:

  1. 檢查__iter__方法。如果存在,則使用新的迭代協議。

  2. 否則,請嘗試調用__getitem__連續更大的整數值,直到引發IndexError。

(2)曾經是這樣做的唯一方法,但是它有一個缺點,就是它假設支持的只是迭代所需的功能。爲了支持迭代,你必須支持隨機訪問,這對於文件或網絡流等前進很容易的事情來說要昂貴得多,但是往後退卻需要存儲所有內容。 __iter__允許迭代沒有隨機訪問,但由於隨機訪問通常允許迭代,並且因爲打破向後兼容性會很差,所以仍支持__getitem__

5

這是因爲歷史原因。在Python 2.2之前__getitem__是創建可以用for循環迭代的類的唯一方法。在2.2中添加了__iter__協議,但爲了保持向後兼容性,__getitem__仍然適用於for循環。

相關問題