Pythonでの "iterable"、 "iterator"、 "iteration"の最も基本的な定義は何ですか?
複数の定義を読んだことがありますが、正確には理解できないため、正確な意味を特定することはできません。
誰かが素人用語で3つの定義で私を助けてもらえますか?
繰り返し は、何かを次々に取り出すための一般的な用語です。明示的または暗黙的に、ループを使用して項目のグループを移動するときはいつでも、それが反復です。
Pythonでは、 iterable と iterator には特別な意味があります。
iterable は、 iterator を返す__iter__
メソッドを持つオブジェクト、またはゼロから始まる順次インデックスを取ることができる__getitem__
メソッドを定義するオブジェクトです(インデックスがある場合はIndexError
を発生させます)。もう有効ではない)。したがって、 iterable は、 iterator から取得できるオブジェクトです。
イテレータ は、next
(Python 2)または__next__
(Python 3)メソッドを持つオブジェクトです。
Pythonでfor
ループ、map
、またはリスト内包表記などを使用するときはいつでも、next
メソッドが自動的に呼び出され、 iterator から各項目が取得され、 iterationの処理が行われます。 。
学習を開始するのに適した場所は、 チュートリアルの反復子セクション と 標準型ページの反復子タイプセクション です。基本を理解したら、 関数型プログラミングHOWTOのイテレータセクション を試してください。
これが私がPythonクラスを教えるのに使う説明です:
ITERABLEは以下のとおりです。
for x in iterable: ...
またはiter()
を使って呼び出すことができるものは何でも:iter(obj)
または__iter__
を定義するオブジェクト、またはインデックス検索に適した__getitem__
メソッドを持つことができます。ITERATORはオブジェクトです。
__next__
メソッドを使うと:StopIteration
を上げることによってそれが完了したことを知らせるself
を返す__iter__
メソッドがあります)。ノート:
__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
上記の答えは素晴らしいですが、私が見たことのほとんどがそうであるように、区別を私のような人々に十分強調しないでください。
また、人々は前に "Xは__foo__()
メソッドを持つオブジェクト"のような定義を置くことによって "too pythonic"を得る傾向があります。そのような定義は正しいです - 彼らはアヒルタイピング哲学に基づいていますが、その単純さで概念を理解しようとするときメソッドに焦点を合わせることは矛盾する傾向があります。
それで私は私のバージョンを追加します。
自然言語では、
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初心者の実際の経験からトピックを理解する方法の単なるデモンストレーションです。
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
それが誰かに役立つかどうかはわかりませんが、私は常に頭の中で概念を視覚化して、それらをよりよく理解するのが好きです。だから、息子がいるので、レンガと白書で反復可能/反復子の概念を視覚化します。
暗い部屋にいて、床に息子用のレンガがあるとしましょう。異なるサイズ、色のレンガは今では重要ではありません。それらのような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
>>>
助けになるかわかりませんが、助けてくれました。誰かがコンセプトの視覚化を確認/修正できれば、感謝します。もっと学ぶのに役立ちます。
これが私のチートシートです:
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__()
メソッドはジェネレータとして実装できますか?__next__
メソッドは必ずしもイテレータではないのですか?ドキュメンテーション よりもずっとシンプルになるとは思いませんが、試してみます。
イテレータ は、iterable内の次の(または最初の)項目を与える(または保持する)ヘルパー擬似メソッド(または擬似属性)と考えることができます。 (実際には、メソッドnext()
を定義するのは単なるオブジェクトです)
繰り返し はおそらくMerriam-Websterによって最もよく説明されています Wordの定義 :
b:一連のコンピューター命令を指定された回数、または条件が満たされるまで繰り返す - 再帰を比較する
繰り返し可能 : - 繰り返し可能なものは繰り返し可能です。リストや文字列などのようなシーケンスのようなものです。また、__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
iterable = [1, 2]
iterator = iter(iterable)
print(iterator.__next__())
print(iterator.__next__())
そう、
iterable
はオブジェクトであり、ループにすることができます。例えばリスト、文字列、タプルなど.
iter
オブジェクトでiterable
関数を使用すると、イテレータオブジェクトが返されます。
これでiterator objectは__next__
(Python 3では、あるいはPython 2ではちょうどnext
)という名前のメソッドを持つことができます。それによってiterableの各要素にアクセスできます
したがって、上記のコードの出力は次のようになります。
1
2
Iterables 毎回新しいイテレータをインスタンス化する
__iter__
メソッドがあります。イテレータ 個々の項目を返す
__next__
メソッドとself
を返す__iter__
メソッドを実装します。したがって、反復子も反復可能ですが、反復可能子は反復子ではありません。
Luciano Ramalho、流暢なPython。
イテラブルとイテレータを扱う前に、イテラブルとイテレータを決定する主な要素はシーケンスです。
シーケンス:シーケンスはデータの集まりです
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