9

私はPythonにかなり慣れておらず、イテレータオブジェクトを定義するいくつかの例を見ていました。

私が見た例は:

class fibit:  # iterate through fibonacci sequence from 0,1...n<=max
    def __init__(self, max):       
        self.max = max

   def __iter__(self):
        self.a = 0
        self.b = 1
        return self

   def next(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

しかし、self.aとself.bの初期化をiterからinitに移動すると、(私の単純な理解では)まったく同じように機能するように見えます。

class fibit:  # iterate through fibonacci sequence from 0,1...n<=max
    def __init__(self, max):
        self.a = 0
        self.b = 1        
        self.max = max

   def __iter__(self):
        return self

   def next(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

では、これを行うための推奨される方法はどれですか?

ありがとう。:)

4

3 に答える 3

10

で初期化を行う必要があります__init__。それがそこにある理由です。

Python の Iterator オブジェクトは、標準的には「1 回使用」です。一度イテレーターを反復処理すると、それを再度反復処理できるとは想定されていません。

したがって、オブジェクトを再度反復しようとすると、値を再初期化しても意味がありません。これを説明するために、コードを少し拡張しました。

class fibit_iter:  # iterate through fibonacci sequence from 0,1...n<=max
    def __init__(self, max):
        self.max = max

    def __iter__(self):
        self.a = 0
        self.b = 1
        return self

    def next(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

class fibit_init:  # iterate through fibonacci sequence from 0,1...n<=max
    def __init__(self, max):
        self.a = 0
        self.b = 1
        self.max = max

    def __iter__(self):
        return self

    def next(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

iter_iter = fibit_iter(10)
iter_init = fibit_init(10)

print "iter_iter"

for item in iter_iter:
    print item
    break

for item in iter_iter:
    print item
    break

print "iter_init"

for item in iter_init:
    print item
    break

for item in iter_init:
    print item
    break

基本的に、init バージョンからオブジェクトを作成し、iter バージョンからオブジェクトを作成します。次に、両方の部分を 2 回繰り返します。異なる結果が得られることに注意してください。

iter_iter
0
0
iter_init
0
1
于 2013-02-15T17:25:32.950 に答える
2

__init__クラスのインスタンスを初期化するときに使用されます。クラスインスタンスの属性を設定するために使用されます。

__iter__反復可能な (インターレーターを返す) クラスの動作を定義するために使用されます。

@mgilson -__iter__通常、イテレータは値を生成する (破壊的に消費する) という点で、リストとは異なるイテレータを返します (type() は物理的に異なります)。

__iter__()xrange インスタンスのメソッドを呼び出して、値を複数回循環させてみてください。

 >>> foo = xrange(5)
 >>> bar = a.__iter__()
 >>> bar.next()
 0
 >>> bar.next()
 1
 >>> list(bar)
 [2, 3, 4]
于 2013-02-15T17:30:42.420 に答える
1

それは、イテレータに何をさせたいかによって異なります。イテレータを複数回反復して毎回同じ結果を得る正当な理由がある場合は、初期化を__iter__;に入れます。ただし、これは例外であり、標準ではありません。適切に動作するイテレータはraise StopIteration、使い果たされたときにシーケンスを再開するのではなく、続行する必要があります。StopIteration実際、 aが発生した後にそれ以上の値を返すイテレータは壊れていると見なされます (ただし、これは使用方法に注意するための警告です)。

繰り返しになりますが、

  • 標準イテレータの場合、初期化を入れます__init__

  • カスタム/リピート動作の場合は、初期化を入れます__iter__

于 2016-03-24T22:06:30.353 に答える