1

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なし...なし

これを達成するために、誰かが私が欠けているものについて詳しく説明できますか?

4

3 に答える 3

2

非常に複雑な方法でアプローチしている可能性があります。

私はこの方法でこの問題を解決します:

  • 別の例を見てみましょう。あなたは転置に対して対称的であるため、間違ったことをした場合の影響はわかりません。取りましょう

    x = [[1, 2, 3, 4], [5, 6, 7, 8]]
    

今のところ。

  • zip()または(大きなリストの場合)を使用itertools.izip()して転置し、1つのレベルを削除します。

    y = [j for i in itertools.izip(*x) for j in i]
    

    ここでは、izip()指定されたすべてのリストを繰り返し、それらの1番目、2番目、...の要素を組み合わせて、タプル(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__()returnselfして実装することができますnext()。しかし、私はこれに反対します。

      • 自分でインデックスを追跡する必要があります
      • ここで読むことができるように、一度使い果たされると、このイテレータを再起動することはできません(そしてそうすべきではありません)。

        [...]イテレータのnext()メソッドがStopIterationを発生させると、それ以降の呼び出しでも発生し続けます。このプロパティに従わない実装は、壊れていると見なされます。(この制約はPython 2.3で追加されました。Python2.2では、このルールに従ってさまざまなイテレーターが壊れています。)

        したがって、反復ごとに新しいオブジェクトが必要になります。

    • これは、 PEP234によって提案されているように、イテレータ自体が提供されていない場合にオブジェクトをイテレータにするためのPythonの「最後のリゾートアプローチ」であるため、を使用__getitem__()して面白いことを行うこともできます。

      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)
      
于 2012-10-18T07:01:56.170 に答える
1

__iter__関数は、 self.enviter(self.env)のイテレータを返すを返します。次のメソッドを呼び出す場合は__iter__、を返す必要がありますself。ただし、実装には他の問題があります。たとえば、イテレータが2回以上機能しないなどです。

これを達成するためのより簡単な方法があります。これを実現するために、ジェネレータ式/リスト内包表記を記述できます(@Ericの回答を参照)。ジェネレータメソッドを作成することもできます。例えば:

def iter_column_row():
    for i in range(self.getColumnCount()):
        for j in range(self.getRowCount()):
            yield self.env[j][i]
于 2012-10-18T06:56:48.570 に答える
0
def __iter__(self):
    return (self.env[j][i] for i in range(columnCount)
                           for j in range(rowCount))

Iとjを交換する必要があるかもしれません

于 2012-10-18T06:41:43.103 に答える