今回は Python のイテレータ生成クラスを使う方法についてご紹介します。
Python でイテレータ( iterator )を生成する関数のことを「ジェネレータ」( generator )と呼びますが、関数と同様にクラスを使う形でもイテレータを生成することができます。
具体的には、 __iter__()
メソッドを定義してこれがイテレータを返すようにすれば OK です。その最もかんたんな方法は yield
を使う方法です。
逆に yield
を使わない場合は __iter__()
に加えて __next__()
( Python 2 の場合は next()
)メソッドを定義する必要がありますが、シンプルなケースでは __iter__()
と yield
を使った方法がシンプルかつかんたんです。
サンプルとして、与えられた整数の因数を返すジェネレータクラスを見てみましょう。
# 因数を返すイテレータクラス
class PrimeFactor(object):
// number で対象の数を、 max_count で返す因数の数を指定する
def __init__(self, number, max_count):
self.number = number
self.max_count = max_count
// インスタンスをジェネレータ化する
def __iter__(self):
count = 0
for i in range(2, self.number):
if self.number % i == 0:
count += 1
// 指定された数だけ因数が返されたらイテレータ処理を終了するために StopIteration() 例外をあげる
if count > self.max_count:
raise StopIteration()
yield i
ここで定義した PrimeFactor
は以下の形で使うことができます。
pf = PrimeFactor(number = 100, max_count = 5)
# 1 周目
for n in pf:
print(n, end=", ")
print()
# => 2, 4, 5, 10, 20,
# 2 周目
for n in pf:
print(n, end=", ")
print()
# => 2, 4, 5, 10, 20,
この形で定義されたイテレータ生成オブジェクトは、何度もループで回せるという特徴があります(処理の内容にもよりますが)。一方、ジェネレータ関数で生成されたオブジェクトの場合、ループで回せるのは一般に一度かぎりです。
# PrimeFactor の関数版
def prime_factor(number, max_count):
count = 0
for i in range(2, number):
if number % i == 0:
count += 1
if count > max_count:
raise StopIteration()
yield i
# こちらはいったんループを回したらその後は StopIteration 例外を出し続けるため
# 2 周目のループは実行されない
pf2 = prime_factor(number = 100, max_count = 5)
# 1 周目
for n in pf2:
print(n, end=", ")
print()
# => 2, 4, 5, 10, 20,
# 2 周目
for n in pf2:
print(n, end=", ")
print()
# => 出力なし
ちなみに、この、イテレータを返すオブジェクトのことをイテラブル( iterable )と呼ぶそうです。
以上です。
参考