LoginSignup
1
0

More than 1 year has passed since last update.

Pythonで、ジェネレータを継承して新たなジェネレータを作る

Posted at

環境

Python 3.7.13

クラスの場合

以下のような、2から10までの偶数を返すジェネレータがあるとします。

class Even():
    def __iter__(self):
        yield 2
        yield 4
        yield 6
        yield 8
        yield 10

even_gen = Even()
for i in even_gen:
    print(i)
出力
2
4
6
8
10

このEvenクラスを継承して、2から10までの偶数に加えて1から9までの奇数も返すEvenOddクラスを実装したいとします。
super().__iter__()でスーパークラス側のgenerator-iteratorオブジェクトを得て一度回し、そのあと(あるいはその前に)サブクラス側の実装をします。以下のようになります。

class EvenOdd(Even):
    def __iter__(self):
        yield from super().__iter__()
        yield 1
        yield 3
        yield 5
        yield 7
        yield 9

evenodd_gen = EvenOdd()
for i in evenodd_gen:
    print(i)
出力
2
4
6
8
10
1
3
5
7
9

yield fromを使わずに書くと下記のようになります。

class EvenOdd(Even):
    def __iter__(self):
        super_gen = super().__iter__()
        for i in super_gen:
            yield i

        yield 1
        yield 3
        yield 5
        yield 7
        yield 9

関数の場合

先ほどは2から10までの偶数を返すEvenクラスを定義しましたが、同様にeven()関数を考えてみます。ジェネレータは関数で定義するほうが一般的かもしれません。

def even():
    yield 2
    yield 4
    yield 6
    yield 8
    yield 10

even_gen = even()
for i in even_gen:
    print(i)

このeven()関数を利用して、あらたに1から9までの奇数も返すようにしたeven_odd()関数は下記のように実装できます。

def even_odd():
    yield from even()
    yield 1
    yield 3
    yield 5
    yield 7
    yield 9

evenodd_gen = even_odd()
for i in evenodd_gen:
    print(i)

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0