![Iterator](/images/patterns/cards/iterator-mini.png?id=76c28bb48f997b36965983dd2b41f02e)
Iterator を Python で
Iterator は、 振る舞いに関するデザインパターンの一つで、 複雑なデータ構造の内部の詳細を公開することなく、 順次横断的に探索することを可能とします。
Iterator のおかげで、 クライアントは、 異なるコレクション上の要素の探索を、 単一のイテレーター・インターフェースを使用して同様の方法で行えます。
複雑度:
人気度:
使用例: このパターンは、 Python コードではよく見かけます。 多くのフレームワークやライブラリーがこれを使用してコレクション上の探索の標準的方法を提供します。
見つけ方: Iterator は、 next
や previous
などの操舵用メソッドの存在から簡単に識別できます。 イテレーターを使ったクライアント・コードには、 探索対象のコレクションへの直接のアクセスがないかもしれません。
概念的な例
この例は、 Iterator デザインパターンの構造を説明するためのものです。 以下の質問に答えることを目的としています:
- どういうクラスからできているか?
- それぞれのクラスの役割は?
- パターンの要素同士はどう関係しているのか?
main.py: 概念的な例
from __future__ import annotations
from collections.abc import Iterable, Iterator
from typing import Any
"""
To create an iterator in Python, there are two abstract classes from the built-
in `collections` module - Iterable,Iterator. We need to implement the
`__iter__()` method in the iterated object (collection), and the `__next__ ()`
method in theiterator.
"""
class AlphabeticalOrderIterator(Iterator):
"""
Concrete Iterators implement various traversal algorithms. These classes
store the current traversal position at all times.
"""
"""
`_position` attribute stores the current traversal position. An iterator may
have a lot of other fields for storing iteration state, especially when it
is supposed to work with a particular kind of collection.
"""
_position: int = None
"""
This attribute indicates the traversal direction.
"""
_reverse: bool = False
def __init__(self, collection: WordsCollection, reverse: bool = False) -> None:
self._collection = collection
self._reverse = reverse
self._position = -1 if reverse else 0
def __next__(self) -> Any:
"""
The __next__() method must return the next item in the sequence. On
reaching the end, and in subsequent calls, it must raise StopIteration.
"""
try:
value = self._collection[self._position]
self._position += -1 if self._reverse else 1
except IndexError:
raise StopIteration()
return value
class WordsCollection(Iterable):
"""
Concrete Collections provide one or several methods for retrieving fresh
iterator instances, compatible with the collection class.
"""
def __init__(self, collection: list[Any] | None = None) -> None:
self._collection = collection or []
def __getitem__(self, index: int) -> Any:
return self._collection[index]
def __iter__(self) -> AlphabeticalOrderIterator:
"""
The __iter__() method returns the iterator object itself, by default we
return the iterator in ascending order.
"""
return AlphabeticalOrderIterator(self)
def get_reverse_iterator(self) -> AlphabeticalOrderIterator:
return AlphabeticalOrderIterator(self, True)
def add_item(self, item: Any) -> None:
self._collection.append(item)
if __name__ == "__main__":
# The client code may or may not know about the Concrete Iterator or
# Collection classes, depending on the level of indirection you want to keep
# in your program.
collection = WordsCollection()
collection.add_item("First")
collection.add_item("Second")
collection.add_item("Third")
print("Straight traversal:")
print("\n".join(collection))
print("")
print("Reverse traversal:")
print("\n".join(collection.get_reverse_iterator()), end="")
Output.txt: 実行結果
Straight traversal:
First
Second
Third
Reverse traversal:
Third
Second
First