CodeGym /コース /Python SELF JA /イテレーター

イテレーター

Python SELF JA
レベル 19 , レッスン 4
使用可能

5.1 IterableIterator

すでに知っていると思うけど、イテレーターというのは イテレーターのプロトコルを実装しているオブジェクトで、 コレクションから順番に要素を取得することができるんだ。 Pythonでは、リスト、タプル、文字列のようなシーケンスの要素を反復処理するために広く使われているよ。

イテレーターの仕組みと使い方を見てみよう。

イテラブルオブジェクト (Iterable)

forループでオブジェクトを回すためには、そのオブジェクトが イテラブルでなければならない – Iterableということだね。つまり、 オブジェクトはメソッド__iter__()を 実装している必要があるよ。そのメソッドはイテレーターオブジェクトを返すべきだね。

イテレーターオブジェクト (Iterator)

これは特殊なオブジェクトで、シーケンスの 次の要素を返すメソッド __next__()を持っているんだ。 要素が終わると、メソッド__next__()StopIteration例外を投げて 反復の終了を示すよ。

イテレーターはまた、メソッド__iter__()を実装して、 自身のイテレーターを返さなければならない。

Pythonの組み込み関数を使用した例

この例では、リストnumbersが イテラブルオブジェクトであるんだ。イテレーターを iter()関数を使って取得し、 next()関数を使って 要素を反復処理するんだ。StopIteration例外が 投げられるまでね。


# イテラブルオブジェクト
numbers = [1, 2, 3, 4, 5]
            
# イテラブルオブジェクトからイテレーターを取得
iterator = iter(numbers)
            
# イテレーターを使って要素を反復処理
try:
    while True:
        number = next(iterator)
        print(number)
except StopIteration:
    pass
        

これはまさにこういうコードを書くときに起こることだね:


# イテラブルオブジェクト
numbers = [1, 2, 3, 4, 5]
            
for number in numbers:
    print(number)
        

5.2 イテレーターの本質

イテレーターは要素のグループを順番に巡るのを助けてくれるオブジェクトだよ。実装はさまざまだけど、イテレーターに求められる すべての要件を実装する自分のクラスを書いてみよう。

ステップ 1. まずは自分のクラスを作成

startからendまでの数字を順番に返すようにしよう


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        

ステップ 2. __iter__メソッドのサポート

ここでは__iter__メソッドを追加して、__next()__メソッドを呼び出すイテレーターオブジェクトを返すようにするんだ。 自分のオブジェクトの参照を返しても問題ないよ。


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        

ステップ 3. __next__メソッドのサポート

イテレーターオブジェクトに次の要素を返すメソッド__next__を追加する必要があるね。 変数currentを使って単に次の要素を返すよ:


def __next__(self):
    current = self.current
    self.current += 1
    return current
        

ステップ 4. イテレーターを停止する

イテレーターがすでにすべての予定されていた値を返したら、例外StopIterationを投げる必要があるね。 最後の関数を少し修正しよう:


def __next__(self):
    if self.current >= self.end:
        raise StopIteration
    current = self.current
    self.current += 1
    return current
        

いい感じ。これでイテレーターを使えるようになったね。ここに全体のコードの例があるよ:


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        current = self.current
        self.current += 1
        return current
        
# カスタムイテレーターのインスタンスを作成
my_iter = MyIterator(1, 5)
        
# イテレーターを使って要素を反復処理
for num in my_iter:
    print(num)

5.3 正しいイテレーター

前の例のイテレーターの何が悪いのか?そうだね、動くけど少し単純すぎるんだ。同じ要素のコレクションを複数のイテレーターで同時に巡ることができない。

メソッド__iter__で自身を返すのではなく、別のオブジェクトを返すコードを書くのが正しいだろうね。それがすべての要素を正しく返すようにするんだ。

例:


class MyIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return MyIterator(self.data)
    
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        item = self.data[self.index]
        self.index += 1
        return item
    
# 使用例
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
    print(item)
    

この例では、2つのクラスがあるね — 最初のクラスにはイテレーターで進むコレクションが渡されるんだ。2番目のクラスがイテレーターで、メソッドnext()でコレクションの要素を返すんだ。これも非常に簡単だけど、これがクラスにイテレーターを追加する方法だよ。

1
Опрос
モジュールとパッケージ,  19 уровень,  4 лекция
недоступен
モジュールとパッケージ
モジュールとパッケージ
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION