0Pricing
Python Academy · レッスン

イテレータプロトコル

__iter__と__next__を理解します

「イテレータプロトコル」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。

イテレーションとは何ですか?

リスト、文字列、辞書に対してforループを記述するとき、Pythonは内部でイテレータプロトコルを使用しています。

ループ処理できるオブジェクトをイテラブルと呼びます。実際に値を1つずつ生成するものをイテレータと呼びます。

for ch in 'abc':
    print(ch)

iter()とnext()

イテレーションを動かす組み込み関数は2つあります。

  • iter(obj)は、イテラブルにイテレータを要求します。
  • next(it)は、イテレータに次の値を要求します。

値が残っていない場合、next()はStopIterationを発生させます。

it = iter([10, 20, 30])
print(next(it))
print(next(it))
print(next(it))

StopIteration

next()を必要な回数より1回多く呼び出すと、StopIterationが発生します。forループはこれを自動的に捕捉し、正常に停止します。

it = iter([1])
print(next(it))
try:
    next(it)
except StopIteration:
    print('No more items')

2つのダンダーメソッド

独自のイテレータを作成するには、2つのメソッドを実装します。

  • __iter__は、イテレータオブジェクト自身を返します。
  • __next__は、次の値を返すか、StopIterationを発生させます。
class Count:
    def __init__(self, n):
        self.i = 0
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= self.n:
            raise StopIteration
        self.i += 1
        return self.i

for x in Count(3):
    print(x)

イテラブルとイテレータ

イテラブルに必要なのは__iter__だけです。イテレータには__iter__と__next__の両方が必要です。

リストはイテラブルですが、イテレータではありません。iter()を呼び出すたびに、新しいイテレータが得られます。

nums = [1, 2, 3]
print(iter(nums) is iter(nums))
it = iter(nums)
print(it is iter(it))

イテレータは一度だけ使い切られる

イテレータは一度だけ消費できます。末尾に到達すると、空のままになります。もう一度ループするには、新しいイテレータを作成します。

it = iter([1, 2])
print(list(it))
print(list(it))

range風のイテレータ

単純なカウンターのように動作する独自のイテレータを作成しましょう。状態がインスタンスに保持されている点に注目してください。

class EvenUpTo:
    def __init__(self, limit):
        self.cur = 0
        self.limit = limit
    def __iter__(self):
        return self
    def __next__(self):
        if self.cur > self.limit:
            raise StopIteration
        value = self.cur
        self.cur += 2
        return value

print(list(EvenUpTo(8)))

イテラブルとイテレータを分離する

よりすっきりした設計では、コンテナーとイテレータを分離します。これにより、コンテナーを何度もループ処理できます。

class Bag:
    def __init__(self, items):
        self.items = items
    def __iter__(self):
        return BagIterator(self.items)

class BagIterator:
    def __init__(self, items):
        self.items = items
        self.i = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= len(self.items):
            raise StopIteration
        v = self.items[self.i]
        self.i += 1
        return v

b = Bag(['x', 'y'])
print(list(b))
print(list(b))

デフォルト値付きでnext()を使う

next(it, default)は、イテレータが空の場合にStopIterationを発生させず、デフォルト値を返します。安全に先読みしたいときに便利です。

it = iter([42])
print(next(it, 'done'))
print(next(it, 'done'))

イテレータはメモリ効率に優れている

イテレータは一度に1つの項目を生成するため、シーケンス全体をメモリに保持する必要がありません。そのため、非常に大きなストリームや無限ストリームにも対応できます。

class Naturals:
    def __init__(self):
        self.n = 0
    def __iter__(self):
        return self
    def __next__(self):
        self.n += 1
        return self.n

it = iter(Naturals())
print(next(it), next(it), next(it))

イテレーターを消費する組み込み関数

多くの組み込み関数は、任意のイテレーターを受け取れます。sum、max、min、sorted、list、tupleなどです。これらはStopIterationが発生するまで値を取り出します。

class Count:
    def __init__(self, n):
        self.i = 0
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= self.n:
            raise StopIteration
        self.i += 1
        return self.i

print(sum(Count(5)))
print(max(Count(5)))

理解度チェック

イテレータープロトコルの理解度を確認しましょう。

まとめ

イテレータープロトコルについて学びました。

  • iter()でイテレーターを取得し、next()で値を取り出します。
  • StopIterationが終了を示し、forがそれを処理します。
  • カスタムイテレーターでは、__iter__と__next__を実装します。
  • イテレーターは一度しか使用できず、メモリ効率にも優れています。

次は、yieldを使ってPythonにイテレーターを書かせます。

よくある質問

「イテレータプロトコル」レッスンは無料ですか?

はい。「イテレータプロトコル」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。

「イテレータプロトコル」で何を学びますか?

__iter__と__next__を理解します ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Python Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「イテレータプロトコル」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPython Academyレッスンでコードを書いて実行できますか?

はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. イテレータプロトコル
  2. ジェネレータ関数
  3. ジェネレータ式
  4. yield fromと委譲
← Python Academyに戻る