簡體   English   中英

Python __iter__和next()函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM