[英]Python __iter__ and next() functions
在Python中......
我有一個在類中定義的嵌套列表:
self.env = [[ None for i in range(columnCount)] for j in range(rowCount) ]
出於此問題的目的,我們假設此嵌套列表包含以下值:
[None, None, None, None]
[None, None, None, None]
[None, None, 0, None]
[None, None, None, None]
我需要能夠利用iter和next()方法按列主要順序(row0,col0 row1,col0,row2,col0 ......)瀏覽此列表。
其目的是將位於該網格位置的值發送到另一個函數以進行處理。
到目前為止,我將iter函數定義為:
def __iter__(self):
return iter(self.env)
然后我將下一個函數定義為:
def next(self):
self.currentRow += 1
self.currentColumn += 1
if ( (self.currentRow < self.getRowCount()) and (self.currentColumn < self.getColumnCount()) ):
return self.env[self.currentRow][self.currentColumn]
else:
raise StopIteration
我遇到的問題是iter函數似乎將每一行作為列表返回,但它沒有調用下一個方法來進一步處理該列表。
我的目標是在每個網格位置單獨打印值...如下:
無無...無0無......無
有人可以詳細說明我想要的是什么,以實現這一目標嗎?
你可能會以一種過於復雜的方式接近。
我會這樣解決這個問題:
再舉一個例子 - 你的移調是對稱的,所以你看不出做錯的效果。 讓我們來
x = [[1, 2, 3, 4], [5, 6, 7, 8]]
目前。
使用zip()
或(對於大列表)可能更好的itertools.izip()
用於轉置它,並刪除一個級別:
y = [j for i in itertools.izip(*x) for j in i]
在這里, izip()
迭代所有給定的列表並組合它們的1st,2nd,...元素以產生元組(1, 5), (2, 6)
等等。 i
遍歷這些元組, j
遍歷他們的項目。 所以y
是[1, 5, 2, 6, 3, 7, 4, 8]
。
現在,如果您希望您的類實例以這種方式進行迭代,您可以采用以下幾種方法:
您可以__iter__()
作為生成器函數或返回迭代器,例如
def __iter__(self): return (j for i in itertools.izip(*self.env) for j in i) def __iter__(self): for i in itertools.izip(*self.env): for j in i: yield i def __iter__(self): return iter([j for i in itertools.izip(*self.env) for j in i])
這樣,您的對象是可迭代的,但不是迭代器。
你可以按照你的意圖讓你的對象成為它自己的迭代器,讓__iter__()
返回self
並實現next()
。 但是,我會反對這一點
一旦用盡,你可以(而且應該)不重啟這個迭代器,你可以在這里閱讀:
[...]一旦迭代器的next()方法引發StopIteration,它將繼續在后續調用中這樣做。 不遵守此屬性的實現被視為已損壞。 (這個約束是在Python 2.3中添加的;在Python 2.2中,根據此規則會破壞各種迭代器。)
因此,每次迭代都需要一個新對象。
您甚至可以使用__getitem__()
來做有趣的事情,因為這是Python的“最后一個ressort方法”,如果它不提供迭代器本身,則使對象可迭代,如PEP234所建議的:
def __getitem__(self, index): if index >= len(self): raise IndexError # do a complicated calculation to map from this single index to your `self.env` def __len__(self): # not needed, but handy return sum(len(i) for i in self.env)
你的__iter__
函數返回iter(self.env)
,它返回self.env的迭代器。 如果你想要調用你的下一個方法__iter__
,你應該返回self
。 但是在您的實現中還存在其他問題,例如,您的迭代器將不會多次運行。
有更簡單的方法來實現這一目標。 您可以編寫生成器表達式/列表理解來實現此目的(請參閱@ Eric的答案)。 您還可以編寫生成器方法 。 例如:
def iter_column_row():
for i in range(self.getColumnCount()):
for j in range(self.getRowCount()):
yield self.env[j][i]
def __iter__(self):
return (self.env[j][i] for i in range(columnCount)
for j in range(rowCount))
可能需要交換I和j
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.