爲什麼在一個類上定義__getitem__可迭代?爲什麼在一個類上定義__getitem__使它在python中迭代?
舉例來說,如果我寫的:
class b:
def __getitem__(self, k):
return k
cb = b()
for k in cb:
print k
我得到的輸出:
0
1
2
3
4
5
6
7
8
...
我真的希望看到 「在CB爲K:」 從返回一個錯誤
爲什麼在一個類上定義__getitem__可迭代?爲什麼在一個類上定義__getitem__使它在python中迭代?
舉例來說,如果我寫的:
class b:
def __getitem__(self, k):
return k
cb = b()
for k in cb:
print k
我得到的輸出:
0
1
2
3
4
5
6
7
8
...
我真的希望看到 「在CB爲K:」 從返回一個錯誤
如果你看一看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().
因爲cb[0]
與cb.__getitem__(0)
相同。請參閱python documentation。
特殊方法如__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循環的東西。
迭代對__getitem__
支持可以看作是其允許平滑的過渡時PEP234介紹iterability爲主要概念的「傳統特色」。它只適用於沒有__iter__
的類,其__getitem__
接受整數0,1,& c,並且一旦索引變得太高(如果有的話)就引發IndexError
,典型地,在__iter__
之前編碼的典型「序列」類(儘管沒有阻止你編碼新的類這也是)。個人而言,我寧願不在新代碼中依賴這個,雖然它並沒有被廢棄,也沒有消失(在Python 3中也能正常工作),所以這只是一個風格和品味的問題(「顯式更好而不是隱含的「,所以我寧願明確地支持迭代,而不是依靠__getitem__
支持它隱含地爲我 - 但不是一個bigge)。
當`__getitem__`被引入創建迭代器時,是否在考慮了`[]`屬性訪問的情況下完成?從閱讀答案看來,如果你想`````````訪問_和_一個迭代,你不能只使用`__getitem__`來完成。你應該使用`__getitem__`來訪問``]`和`__iter__`,對嗎? – lmichelbacher 2012-08-11 23:04:01
@lmichelbacher:當然你可以看到FogleBird的回答 – kriss 2013-09-06 14:10:23
__getitem__
早於迭代器協議,並且在過去的只有方式使事情迭代。因此,它仍然是一種迭代方法。本質上,用於迭代的協議是:
檢查__iter__
方法。如果存在,則使用新的迭代協議。
否則,請嘗試調用__getitem__
連續更大的整數值,直到引發IndexError。
(2)曾經是這樣做的唯一方法,但是它有一個缺點,就是它假設支持的只是迭代所需的功能。爲了支持迭代,你必須支持隨機訪問,這對於文件或網絡流等前進很容易的事情來說要昂貴得多,但是往後退卻需要存儲所有內容。 __iter__
允許迭代沒有隨機訪問,但由於隨機訪問通常允許迭代,並且因爲打破向後兼容性會很差,所以仍支持__getitem__
。
這是因爲歷史原因。在Python 2.2之前__getitem__是創建可以用for循環迭代的類的唯一方法。在2.2中添加了__iter__協議,但爲了保持向後兼容性,__getitem__仍然適用於for循環。
True,但__getitem __()與__iter __()不同。 – grieve 2009-05-29 15:27:31