web-dev-qa-db-ja.com

正確には、反復子、反復可能、および反復とは何ですか?

Pythonでの "iterable"、 "iterator"、 "iteration"の最も基本的な定義は何ですか?

複数の定義を読んだことがありますが、正確には理解できないため、正確な意味を特定することはできません。

誰かが素人用語で3つの定義で私を助けてもらえますか?

372
thechrishaddad

繰り返し は、何かを次々に取り出すための一般的な用語です。明示的または暗黙的に、ループを使用して項目のグループを移動するときはいつでも、それが反復です。

Pythonでは、 iterable iterator には特別な意味があります。

iterable は、 iterator を返す__iter__メソッドを持つオブジェクト、またはゼロから始まる順次インデックスを取ることができる__getitem__メソッドを定義するオブジェクトです(インデックスがある場合はIndexErrorを発生させます)。もう有効ではない)。したがって、 iterable は、 iterator から取得できるオブジェクトです。

イテレータ は、next(Python 2)または__next__(Python 3)メソッドを持つオブジェクトです。

Pythonでforループ、map、またはリスト内包表記などを使用するときはいつでも、nextメソッドが自動的に呼び出され、 iterator から各項目が取得され、 iterationの処理が行われます。

学習を開始するのに適した場所は、 チュートリアルの反復子セクション標準型ページの反復子タイプセクション です。基本を理解したら、 関数型プログラミングHOWTOのイテレータセクション を試してください。

446
agf

これが私がPythonクラスを教えるのに使う説明です:

ITERABLEは以下のとおりです。

  • ループ可能なもの(つまり、文字列やファイルをループできるもの)または
  • forループの右側に表示される可能性があるものすべて:for x in iterable: ...または
  • iTERATORを返すiter()を使って呼び出すことができるものは何でも:iter(obj)または
  • 新しいITERATORを返す__iter__を定義するオブジェクト、またはインデックス検索に適した__getitem__メソッドを持つことができます。

ITERATORはオブジェクトです。

  • 反復中の位置を覚えている状態で、
  • __next__メソッドを使うと:
    • 反復の次の値を返します
    • 次の値を指すように状態を更新します
    • StopIterationを上げることによってそれが完了したことを知らせる
  • それは自己反復可能です(つまり、selfを返す__iter__メソッドがあります)。

ノート:

  • Python 3の__next__メソッドは、Python 2ではnextと綴られています。
  • 組み込み関数next()は、渡されたオブジェクトに対してそのメソッドを呼び出します。

例えば:

>>> s = 'cat'      # s is an ITERABLE
                   # s is a str object that is immutable
                   # s has no state
                   # s has a __getitem__() method 

>>> t = iter(s)    # t is an ITERATOR
                   # t has state (it starts by pointing at the "c"
                   # t has a next() method and an __iter__() method

>>> next(t)        # the next() function returns the next value and advances the state
'c'
>>> next(t)        # the next() function returns the next value and advances
'a'
>>> next(t)        # the next() function returns the next value and advances
't'
>>> next(t)        # next() raises StopIteration to signal that iteration is complete
Traceback (most recent call last):
...
StopIteration

>>> iter(t) is t   # the iterator is self-iterable
289

上記の答えは素晴らしいですが、私が見たことのほとんどがそうであるように、区別を私のような人々に十分強調しないでください。

また、人々は前に "Xは__foo__()メソッドを持つオブジェクト"のような定義を置くことによって "too pythonic"を得る傾向があります。そのような定義は正しいです - 彼らはアヒルタイピング哲学に基づいていますが、その単純さで概念を理解しようとするときメソッドに焦点を合わせることは矛盾する傾向があります。

それで私は私のバージョンを追加します。


自然言語では、

  • iteration は、要素の行から一度に1つの要素を取り出すプロセスです。

Pythonでは、

  • iterable は反復可能なオブジェクトです。単純に言えば、反復で使用できることを意味します。 forループを使って。どうやって? iteratorを使うことによって。以下に説明します。

  • ... while イテレータ は、実際にどのように行うか _を定義するオブジェクトです - 具体的には次は何要素です。それがnext()メソッドを持たなければならない理由です。

イテレータもそれ自体が反復可能です。ただし、その項目が以前の__iter__()の呼び出しによって消費されたかどうかにかかわらず、それらのnext()メソッドは同じオブジェクト(self)を返します。


それでfor x in obj:ステートメントを見たときにPythonインタプリタはどう思いますか?

forループを見てください。イテレータの仕事のように見えます...手に入れましょう。 ...このobjの男がいるので、彼に聞いてみましょう。

objさん、イテレータはありますか?」 (...はiter(obj)を呼び出します。これはobj.__iter__()を呼び出します。これは嬉しい新しいイテレータ_iを渡します。)

わかりました、それは簡単でした...それでは繰り返し始めましょう。 (x = _i.next() ... x = _i.next()...)

obj氏はこのテストに成功したので(あるメソッドが有効なイテレータを返すことによって)、私たちは形容詞で彼に報酬を与えます:あなたは今彼を "iterable Mr. obj"と呼ぶことができます。

ただし、単純な場合では、通常、反復子と反復可能性を別々に持つことによるメリットはありません。それであなたはone only objectを定義します。それはまたそれ自身のイテレータです。 (Pythonは、objによって配布された_iがそれほど輝いているわけではなく、obj自体だけであることを気にかけていません。)

これが私が見たほとんどの例(そして何度も何度も私を混乱させていたもの)で、あなたが見ることができる理由です:

class IterableExample(object):

    def __iter__(self):
        return self

    def next(self):
        pass

の代わりに

class Iterator(object):
    def next(self):
        pass

class Iterable(object):
    def __iter__(self):
        return Iterator()

ただし、項目を1行にしたいが「カーソル」をもっと多くしたい場合など、反復子を反復可能要素から分離することでメリットが得られる場合があります。たとえば、「current」要素と「comingcoming」要素を操作したい場合は、両方に別々のイテレータを使用できます。あるいは、巨大なリストから複数のスレッドを引き出すことができます。それぞれがすべての項目を横断するための独自のイテレータを持つことができます。上記の @ Raymondの および @ glglglの answerを参照してください。

あなたができることを想像してみてください。

class SmartIterableExample(object):

    def create_iterator(self):
        # An amazingly powerful yet simple way to create arbitrary
        # iterator, utilizing object state (or not, if you are fan
        # of functional), magic and nuclear waste--no kittens hurt.
        pass    # don't forget to add the next() method

    def __iter__(self):
        return self.create_iterator()

ノート:

  • 繰り返しますが、反復子は反復可能ではありませんです。イテレータはforループの中で「ソース」として使用することはできません。 forループが主に必要とするのは__iter__()です(これはnext()で何かを返します)。

  • もちろん、forが唯一の繰り返しループではないので、上記は他のいくつかの構成にも当てはまります(while...)。

  • イテレータのnext()はStopIterationをスローして繰り返しを止めることができます。しかし、必ずしも繰り返す必要はありませんし、他の方法を使用することもできます。

  • 上記の「思考プロセス」では、_iは実際には存在しません。私はその名前を作りました。

  • Python 3.xでは小さな変更があります:next()メソッド(組み込みではない)は__next__()と呼ばれる必要があります。はい、それはずっとそうだったはずです。

  • イテレータブルはデータを持ち、イテレータは次の項目を引っ張ります。

免責事項:私はPythonインタプリタの開発者ではないので、インタプリタが「どう思う」かについては本当にわかりません。上記の黙想は、私が他の説明、実験、そしてPython初心者の実際の経験からトピックを理解する方法の単なるデモンストレーションです。

92
Alois Mahdal

Iterableは__iter__()メソッドを持つオブジェクトです。 list()sやTuple()sのように、何度も繰り返すことができます。

反復子は反復するオブジェクトです。それは__iter__()メソッドによって返され、それ自身の__iter__()メソッドを介してそれ自身を返し、next()メソッドを持ちます(3.xの__next__())。

反復はこのnext()を呼び出すプロセスです。 StopIterationが発生するまで__next__()

例:

>>> a = [1, 2, 3] # iterable
>>> b1 = iter(a) # iterator 1
>>> b2 = iter(a) # iterator 2, independent of b1
>>> next(b1)
1
>>> next(b1)
2
>>> next(b2) # start over, as it is the first call to b2
1
>>> next(b1)
3
>>> next(b1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> b1 = iter(a) # new one, start over
>>> next(b1)
1
20
glglgl

それが誰かに役立つかどうかはわかりませんが、私は常に頭の中で概念を視覚化して、それらをよりよく理解するのが好きです。だから、息子がいるので、レンガと白書で反復可能/反復子の概念を視覚化します。

暗い部屋にいて、床に息子用のレンガがあるとしましょう。異なるサイズ、色のレンガは今では重要ではありません。それらのような5つのレンガがあるとします。これらの5つのレンガはobject –たとえばbricks kitとして記述できます。このブリックキットを使用して多くのことができます。1つ取ってから2つ目、次に3つ目を取り、レンガの場所を変更し、最初のレンガを2つ目の上に置くことができます。それらを使っていろいろなことができます。したがって、このブリックキットは反復可能なオブジェクトまたはシーケンスです。各ブリックを通過して、それで何かを行うことができます。私たちは幼い息子のようにしかできません。one brick at at)で遊ぶことができます。繰り返しになりますが、このブリックキットは反復可能であると思います。

今、私たちは暗い部屋にいることを思い出してください。またはほとんど暗い。問題は、これらのレンガ、それらの色、形状などがはっきりと見えないことです。そのため、何かをしたい場合でも、別名繰り返し処理 –実際にはそうではありません暗すぎるので、何をどのように知るか。

私たちにできることは、レンガキットの要素としての最初のレンガの近くです。最初のレンガ要素がどこにあるかを確認するために、白い蛍光紙を置くことができます。そして、キットからレンガを取り出すたびに、暗い部屋でそれを見ることができるように、白い紙を次のレンガに交換します。この白い紙はイテレータにすぎません。 オブジェクトも同様です。しかし、反復可能なオブジェクトの要素を使用して作業および再生できるオブジェクト、つまりブリックキット。

ちなみに、IDLEで次のことを試みてTypeErrorを受け取ったときの初期の間違いを説明しています。

 >>> X = [1,2,3,4,5]
 >>> next(X)
 Traceback (most recent call last):
    File "<pyshell#19>", line 1, in <module>
      next(X)
 TypeError: 'list' object is not an iterator

リストXはレンガキットでしたが、白い紙ではありませんでした。最初にイテレータを見つける必要がありました。

>>> X = [1,2,3,4,5]
>>> bricks_kit = [1,2,3,4,5]
>>> white_piece_of_paper = iter(bricks_kit)
>>> next(white_piece_of_paper)
1
>>> next(white_piece_of_paper)
2
>>>

助けになるかわかりませんが、助けてくれました。誰かがコンセプトの視覚化を確認/修正できれば、感謝します。もっと学ぶのに役立ちます。

9
Nikolay Dudaev

これが私のチートシートです:

 sequence
  +
  |
  v
   def __getitem__(self, index: int):
  +    ...
  |    raise IndexError
  |
  |
  |              def __iter__(self):
  |             +     ...
  |             |     return <iterator>
  |             |
  |             |
  +--> or <-----+        def __next__(self):
       +        |       +    ...
       |        |       |    raise StopIteration
       v        |       |
    iterable    |       |
           +    |       |
           |    |       v
           |    +----> and +-------> iterator
           |                               ^
           v                               |
   iter(<iterable>) +----------------------+
                                           |
   def generator():                        |
  +    yield 1                             |
  |                 generator_expression +-+
  |                                        |
  +-> generator() +-> generator_iterator +-+

クイズ:どうやってわかりますか。

  • すべてのイテレータはイテラブルですか?
  • コンテナオブジェクトの__iter__()メソッドはジェネレータとして実装できますか?
  • iterableと__next__メソッドは必ずしもイテレータではないのですか?
7
AXO

ドキュメンテーション よりもずっとシンプルになるとは思いませんが、試してみます。

  • 反復可能な は、反復 overになり得るものです。実際には通常シーケンスを意味します。始まりと終わりがあり、その中のすべての項目を通過するための何らかの方法があるもの。
  • イテレータ は、iterable内の次の(または最初の)項目を与える(または保持する)ヘルパー擬似メソッド(または擬似属性)と考えることができます。 (実際には、メソッドnext()を定義するのは単なるオブジェクトです)

  • 繰り返し はおそらくMerriam-Websterによって最もよく説明されています Wordの定義

b:一連のコンピューター命令を指定された回数、または条件が満たされるまで繰り返す - 再帰を比較する

3
Kimvais

繰り返し可能 : - 繰り返し可能なものは繰り返し可能です。リストや文字列などのようなシーケンスのようなものです。また、__getItem__()メソッドまたはイテレータを返すiter()関数のいずれかを持っています。

イテレータ : - iterableのiter()メソッドからイテレータオブジェクトを取得したとき。 1つずつ要素を取得するために__next__()メソッド(python3の場合)または単にnext()(python2の場合)を呼び出します。このクラスまたはこのクラスのインスタンスはイテレータと呼ばれます。

ドキュメントより: -

イテレータの使用はPythonを普及させ統一します。舞台裏では、for文はコンテナオブジェクトに対してiter()を呼び出します。この関数は、コンテナ内の要素に1つずつアクセスするメソッド__next__()を定義するイテレータオブジェクトを返します。それ以上要素がなくなると、__next__()はStopIteration例外を発生させ、forループに終了を指示します。 __next__()組み込み関数を使用してnext()メソッドを呼び出すことができます。この例は、すべてがどのように機能するかを示しています。

>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    next(it)
StopIteration

クラスの元: -

class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]


>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
...     print(char)
...
m
a
p
s
3
Vicrobot
iterable = [1, 2] 

iterator = iter(iterable)

print(iterator.__next__())   

print(iterator.__next__())   

そう、

  1. iterableオブジェクトであり、ループにすることができます。例えばリスト、文字列、タプルなど.

  2. iterオブジェクトでiterable関数を使用すると、イテレータオブジェクトが返されます。

  3. これでiterator object__next__(Python 3では、あるいはPython 2ではちょうどnext)という名前のメソッドを持つことができます。それによってiterableの各要素にアクセスできます

したがって、上記のコードの出力は次のようになります。

1

2

2
arpan kumar

Iterables 毎回新しいイテレータをインスタンス化する__iter__メソッドがあります。

イテレータ 個々の項目を返す__next__メソッドとselfを返す__iter__メソッドを実装します。

したがって、反復子も反復可能ですが、反復可能子は反復子ではありません。

Luciano Ramalho、流暢なPython。

1
trthhrtz

イテラブルとイテレータを扱う前に、イテラブルとイテレータを決定する主な要素はシーケンスです。

シーケンス:シーケンスはデータの集まりです

Iterable:Iterメソッドをサポートするシーケンス型オブジェクトです。

Iterメソッド:Iterメソッドは入力としてシーケンスを取り、イテレータと呼ばれるオブジェクトを作成します

イテレータ:イテレータは、nextメソッドを呼び出し、シーケンスを横断するオブジェクトです。nextメソッドを呼び出すと、現在横断しているオブジェクトを返します。

例:

x=[1,2,3,4]

xはデータの集合からなるシーケンスです

y=iter(x)

Iter(x)を呼び出すと、xオブジェクトにiterメソッドがある場合にのみイテレータを返します。それ以外の場合は例外を発生させます。

y=[1,2,3,4]

Yはイテレータなのでnext()メソッドをサポートしています

Nextメソッドを呼び出すと、リストの個々の要素を1つずつ返します。

次のメソッドを再度呼び出した場合、シーケンスの最後の要素が返された後、StopIterationエラーが発生します。

例:

>>> y.next()
1
>>> y.next()
2
>>> y.next()
3
>>> y.next()
4
>>> y.next()
StopIteration
1
Shadow