2009-06-22 6 views
2

Pythonでは、2つの異なる種類のイテレータをサポートするクラスを作成しようとしています。おおまかに言えば、このオブジェクトにはデータの行列が含まれています。行の反復と列の反復をサポートするために2種類のイテレータを使用したいと思います。1つのpythonオブジェクトのデュアルイテレータ

答えて

2

さて、それぞれが発電機である2つの別々の方法を作成してください。

class Matrix(object): 
    def iter_rows(self): 
     for row in self.rows: 
      yield row 

    def iter_columns(self): 
     for column in self.columns: 
      yield column 

私はまったく__iter__を有していないお勧めしますけれどもあなた__iter__は、デフォルトでは、どちらか一方を反復処理することができます。

+0

matrix'の行のための '書き込む能力は、従って、全く__iter__を有していないよりも何とか__iter__定義した方が良いのPython構文の重要な部分です。 – jfs

4

これはあなたの探しているものですか?

class Matrix(object): 
    def __init__(self, rows): 
     self._rows = rows 

    def columns(self): 
     return zip(*self._rows) 

    def rows(self): 
     return self._rows 

# Create a Matrix by providing rows. 
m = Matrix([[1,2,3], 
      [4,5,6], 
      [7,8,9]]) 

# Iterate in row-major order. 
for row in m.rows(): 
    for value in row: 
     print value 

# Iterate in column-major order. 
for column in m.columns(): 
    for value in column: 
     print value 

あなたはオンデマンドで各列を作成する場合は、itertools.izipの代わりzipを使用することができます。

また、実際の値の反復をクラスに移動することもできます。行/列(図のように)を反復したい場合、またはの値がの行/列にあるかどうかはわかりませんでした。

5

dictには、いくつかの反復子生成メソッドがあります - iterkeysitervaluesiteritems - クラスもそうです。 「最も自然な」反復方法が1つある場合は、便宜と可読性のために別名__iter__に別名を付ける必要があります(iterrowsになるはずですが、当然のことながら、dictと同じように、反復動作ですが、合理的なピックはnoneより優れています)。

例えば、行列が正方形であり、行優先リストself.dataにフラット化され、一辺がself.nであるとします。その後:

def iterrows(self): 
    start = 0 
    n = self.n 
    data = self.data 
    while start < n*n: 
    stop = start + n 
    yield data[start:stop] 
    start = stop 

def itercols(self): 
    start = 0 
    n = self.n 
    data = self.data 
    while start < n: 
    yield data[start::n] 
    start += 1 

__iter__ = iterrows 
+0

iterrowsを実装するために、なぜxrange(0、self.n * self.n、self.n)のstart(self.data [start:start + self.n] –

+0

私はちょうど好都合なときに自分自身を吊り上げるほうが好きです。反復の間に変更するはずがないが、Pythonはその最適化をしません。しかし、効率的に反復する方法は複数ありますが、ここの2つのケースの対称性が好きです。 –

関連する問題