Python3:自作クラスとイテレーターの実装

スポンサーリンク

バイオインフォマティクスでは、大量のデータを扱うことが多く、効率的なデータ処理が求められます。その際に役立つのが**オブジェクト指向プログラミング(OOP)**の考え方です。特に、「イテレーター(iterator)」の仕組みを理解し、自作クラスで実装できるようになると、データ解析をよりスムーズに行うことができます。

本記事では、Pythonにおけるイテレーターの基本概念を説明し、実際にバイオインフォマティクスで役立つような自作イテレーターの例を紹介します。


1. イテレーターとは?

Pythonのイテレーターとは、要素を順番に取得できるオブジェクトのことです。例えば、for ループでリストやタプルを順に処理する場合、Pythonの内部でイテレーターが使用されています。

numbers = [1, 2, 3]
for num in numbers:
    print(num)

上記のコードでは、numbers のイテレーターが内部で作成され、num に順次値が渡されます。では、イテレーターの動作をより詳細に理解するために、iter()next() を使ってリストを手動でイテレーションしてみましょう。

numbers = [1, 2, 3]
it = iter(numbers)  # イテレーターを取得
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3

イテレーターは、__iter__() メソッドと __next__() メソッドを実装したオブジェクトのことを指します。


2. 自作クラスでイテレーターを実装する

では、Pythonのオブジェクト指向の考え方を活用し、自作クラスでイテレーターを実装してみましょう。ここでは、シンプルなDNA配列を一塩基ずつイテレーションするクラスを作成します。

(1) 基本のイテレーター実装

class DNAIterator:
    def __init__(self, sequence):
        self.sequence = sequence
        self.index = 0

    def __iter__(self):
        return self  # 自身をイテレーターとして返す

    def __next__(self):
        if self.index >= len(self.sequence):
            raise StopIteration  # 終了条件
        nucleotide = self.sequence[self.index]
        self.index += 1
        return nucleotide

# 使用例
dna_seq = "AGCTTGA"
it = DNAIterator(dna_seq)

for nucleotide in it:
    print(nucleotide)  # A G C T T G A

このクラスの動作は以下の通りです。

  1. __init__() でDNA配列 (sequence) を受け取り、インデックスを0に設定
  2. __iter__() で自分自身を返す(イテレーターとして機能させる)
  3. __next__() で次の塩基を取得し、インデックスを更新(終了時には StopIteration を発生)

3. 応用編:スライディングウィンドウ法のイテレーター

次に、バイオインフォマティクスでよく使われるスライディングウィンドウ法をイテレーターとして実装します。スライディングウィンドウ法は、配列から固定サイズの部分配列を順番に取得する方法で、例えばモチーフ検索やGC含量計算などに使われます。

(2) スライディングウィンドウのイテレーター

class SlidingWindowIterator:
    def __init__(self, sequence, window_size):
        self.sequence = sequence
        self.window_size = window_size
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index + self.window_size > len(self.sequence):
            raise StopIteration  # 終了条件
        window = self.sequence[self.index:self.index + self.window_size]
        self.index += 1  # 1塩基ずつスライド
        return window

# 使用例
dna_seq = "AGCTTGACG"
window_size = 3
it = SlidingWindowIterator(dna_seq, window_size)

for window in it:
    print(window)  # AGC, GCT, CTT, TTG, TGA, GAC, ACG

このイテレーターを使うと、DNA配列の任意の長さの部分配列を順番に取得できます。


4. さらに発展:ジェネレーターとの比較

Pythonには、__iter__()__next__() を使う方法以外に、ジェネレーター(generator) というシンプルなイテレーターの作り方があります。上記のスライディングウィンドウをジェネレーターで書くと、より簡潔になります。

def sliding_window(sequence, window_size):
    for i in range(len(sequence) - window_size + 1):
        yield sequence[i:i + window_size]

# 使用例
dna_seq = "AGCTTGACG"
window_size = 3

for window in sliding_window(dna_seq, window_size):
    print(window)  # AGC, GCT, CTT, TTG, TGA, GAC, ACG

ジェネレーターの利点

  • クラスを定義せずとも、簡潔にイテレーターを作れる
  • yield を使うことでメモリ消費を抑えられる(逐次処理向き)

クラスベースのイテレーターとジェネレーターのどちらを選ぶべきかは、用途によります。クラスベースのイテレーターは、より複雑な状態管理が必要な場合(例えばデータの前処理を組み込む場合)に適しています。一方、単純な反復処理ならジェネレーターの方が手軽です。


5. まとめ

本記事では、Pythonのイテレーターの基本から応用までをバイオインフォマティクスの視点で解説しました。

イテレーターの基本

  • __iter__()__next__() を実装すれば自作クラスをイテレーターにできる

バイオインフォマティクスでの応用

  • DNA配列を一塩基ずつ処理するイテレーター
  • スライディングウィンドウ法のイテレーター

ジェネレーターとの比較

  • クラスベースのイテレーターは状態管理が得意
  • ジェネレーターは簡潔かつメモリ効率が良い

バイオインフォマティクスでは、膨大なデータを扱うため、効率的なデータ処理が重要です。Pythonのイテレーターを活用すれば、柔軟で拡張性のある解析コードを書けるようになります!!

ぜひ実際のプロジェクトで試してみてくださいね〜!

タイトルとURLをコピーしました