Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
今回のPython初心者向け解説は、イテレータ(iterator)です。わかるようでわからない・・・そんなPythonのプログラミング用語の1つですが、その基本的な部分だけをできるだけわかりやすく説明しようとがんばりますので、どうかみなさんも少しがんばって読んでみてください。
Contents
まず言葉の意味を確認しておきましょう。次のようになります。
単語 | 品詞 | 意味 |
---|---|---|
iterate(発音:イテレイト) | 動詞 | 繰り返す |
iterator(発音:イテレーター) | 名詞 | 繰り返しや反復をさせるもの |
このようにもともとは英語の動詞として普通に存在する「iterate」という言葉があって、そこからプログラミングの世界独特の用語として「iterator」という名詞が創造され(?)ました。iteratorはプログラミングの専門用語としての言葉なので、普通の会話や英文で登場することはまずないでしょう。
なお、英語の動詞で「~ate」で終わるものは、名詞化の1つとして「~ator(~する人)」という形になるものが多いです。たとえば、「illustrate(イラストレイト)」→「illustrator(イラストレーターを描く人)」などです。
英語の発音上または普通のカタカナ表記上では、普通はイテレーターというように「ター」となるのですが、コンピューターの世界では語尾を伸ばさずに表記するのが普通らしいので、以下「イテレーター」ではなく、「イテレータ」と書いていきます。また、イテレータもPythonのオブジェクトの1つですが、イテレータオブジェクトを省略して単にイテレータと書いていきます。
Pythonのイテレータとは。次の2つの条件を満たすオブジェクトのことです。
これら2つのメソッドはもともと最初からPythonで用意されているもので、これら2つとも持っていることがイテレータの条件です。逆にいえば、これら2つのメソッドさえ持っていればイテレータとなります。
次にこれら2つのメソッドについて簡単にその機能を見てみましょう。
これら2つのメソッドはそれぞれ次のような機能を持ちます。
メソッド(書き方) | 機能 |
---|---|
オブジェクト.__iter__() | オブジェクトからイテレータを作る。ただしそのオブジェクトがそもそもイテレータだった場合は、そのイテレータであるオブジェクトそのものを返します |
イテレータ.__next__() | イテレータの各要素から1つずつ要素取り出して、要素がなくなればStopIteration 例外を返す。 |
そして上述のように、これら2つのメソッドを2つとも有しているオブジェクトがイテレータです。各メソッドの前にあるオブジェクトの型が異なることに注意してください。__next__()メソッドの対象となるオブジェクトはイテレータです。
上表のように__iter__()メソッドは、
対象となるオブジェクト.__iter__()
という書き方で使いますが、対象となるオブジェクトの種類によって大きく2つに機能が別れます。
オブジェクトの種類 | 機能 |
---|---|
イテレータ | イテレータであるオブジェクトそのものを返す |
それ意外 (ただし__iter__()メソッドを備えるもの) | オブジェクトのイテレータを新しく作成 |
このようにオブジェクトの種類によって機能が変化する点に注意してください。
さて実際に初歩的なコードの具体例から、イテレータの基本的理解を深めていきましょう。
new_list=["A", "B", "C"]
for i in new_list:
print(i)
まずは、このリスト型オブジェクトである「new_list」というリストについて確認しましょう。
インデックス番号(何番目の要素かという情報) | 中身 |
---|---|
0 | Aという文字列データ |
1 | Bという文字列データ |
2 | Cという文字列データ |
これがnew_listの構造になっています。このリスト型オブジェクトが「イテレータではない」ことを確認してみましょう。
イテレータは__iter__メソッドと__next__メソッドとの両方を持つのが条件でしたので、それら2つも持つかどうか調べてみましょう。そのためには、Pyhonのdir関数を使います。このdir関数はオブジェクトがどのような属性や情報を持っているのかを示してくれるものです。
print('__iter__' in dir(new_list))
この場合は「True」が出力されます。つまり、new_listというリスト型オブジェクトは、__iter__()メソッドを持っているということです。
print('__next__' in dir(new_list))
逆にこれは「False」が出力されます。つまり、new_listというリスト型オブジェクトは、__next__()メソッドを持っていないということです。
このようにnew_listは__iter__メソッドしか持っていません。よって、new_listはイテレータではありません。
以上より、Pythonのリストオブジェクトは、イテレータそのものではないとわかりました。Pythonでは、リスト型以外にも辞書型や集合型などなどもイテレータではありません。
では、試しにnew_listのイテレータを作ってみましょう。今回はiter()関数を使って作ってみます(他にも方法はあります)。そして出来たイテレータがきちんと、__iter__()メソッドと__next__()メソッドを有しているか、dir関数を使って確かめてみます。次のコードを書きます。
iterator_of_new_list=iter(new_list)
print('__iter__' in dir(iterator_of_new_list))
print('__next__' in dir(iterator_of_new_list))
1行目でiter()関数を使ってnew_listのイテレータを作ります。2行目と3行目はそれぞれ両メソッドが含まれているかの確認です。
この確認の結果、両メソッドともに「True」が出力されます。つまり、作成されたイテレータであるiterator_of_new_listは、両メソッドとも持っているということになります。
それでは次にfor文とイテレーターとの関係を見ていきましょう。
Pythonのfor文は次のような書き方です。
for_stmt ::= "for" target_list "in" expression_list ":" suite
for文については公式ドキュメントで次のようにその仕組が解説されています。
式リスト(expression_list)は一度だけ評価されます。その結果はイテラブルオブジェクトにならなければなりません。 expression_list の結果に対するイテレータが生成されます。 その後、イテレータが与えるそれぞれの要素に対して、イテレータから返された順に一度づつ、スイート(suite)が実行されます。
ちょっとわかりにくいかもしれませんが、簡単にかけば重要なことは次の2点です。
forのinの後にリスト型のオブジェクトを書いた場合は、上で確認したようにリスト型のオブジェクトは、__iter__()メソッドを持っていますが、__next__()メソッドは持っていません。すなわち、イテレータではなかったのでした。
そして、__iter__()メソッドの機能については再確認となりますが、
オブジェクトの種類 | 機能 |
---|---|
イテレータ | イテレータであるオブジェクトそのものを返す |
それ意外 (ただし__iter__()メソッドを備えるもの) | オブジェクトのイテレータを新しく作成 |
です。
これらを踏まえて、もう一度今回の具体例のコードを見てみましょう。
new_list=["A", "B", "C"]
for i in new_list:
print(i)
この処理の流れを簡単に順番に書いていくと、次のようになります。
for文のinの後に、new_listというリスト型オブジェクトがあります。これ自身はイテレータではないのでnew_listのイテレータが新しく作成される
↓
そして作られたイテレータは__next__()メソッドを持っているため、1つずつ要素をfor文に渡す。
↓
for文はそれを受け取り、1回ずつ処理を実行
という感じです。
上で見たきたように、何度も言いますが、for文のinの後のnew_listというリスト型オブジェクトそのものはイテレータではありません。しかし、それを元にしてイテレータが作成されます。
逆にいえば、イテレータを作ることが可能なオブジェクト(いいかえれば、最低限の機能として、__iter__()メソッドを備えているオブジェクト)が、イテラブルなオブジェクトだと考えることができます。
(イテラブルは英語「iterable」です。意味は「反復可能な」。これはiteratorとは違い、普通の英文でも使われる日常的な(?)単語です)
もちろん、イテレータそのものも__iter__()メソッドを持っているので、イテラブルなオブジェクトという扱いです。すなわち、イテラブルなオブジェクトの1種としてイテレータがあるということです。厳密にいえば、イテラブルなオブジェクトという言葉と、イテレータという言葉は別の意味・概念の用語です。
以上より、Pythonのfor文については、
for ~ in イテラブルなオブジェクト(ただしイテレータ自身もOK):
処理
ということになります。
今回は具体例としてリスト型オブジェクト(new_list)を使いましたが、まさにリスト型オブジェクトはイテラブルなオブジェクトです(__iter__()メソッドを持っているから)。また同様に、辞書型や集合型(set型)オブジェクトも__iter__()メソッドを持っているのでイテラブルなオブジェクトなのです。
そういったオブジェクトがfor文でよく使われるのは、そういった理由?根拠?なのです。
さて、以上のようにイテレータとは、
の2つを同時に持っているオブジェクトというものです。
乱暴にいえば、これら2つのメソッドさえ持っていればなんでもかんでもイテレータです。
したがって、これらのメソッドを定義した自作のイテレータを作ることが可能です。