イテレータプロトコル
__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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- イテレータプロトコル
- ジェネレータ関数
- ジェネレータ式
- yield fromと委譲