Pythonのfor文を高速化する7つの実践的テクニック
こんにちは、とまだです。
Pythonでプログラミングをしていて、「for文の処理が遅くて困った」という経験はありませんか?
実は、Pythonのfor文は書き方次第で処理速度が大きく変わるんです。
今回は、実務で使えるfor文の高速化テクニックを、初心者の方にもわかりやすく解説します。
Pythonのfor文が遅く感じる理由
Pythonは可読性の高さで人気のプログラミング言語です。
しかし、その分かりやすさの裏側で、処理速度が犠牲になることがあります。
なぜfor文が遅くなるのか
for文が遅くなる主な理由は、Pythonがインタープリタ型言語だからです。
コンピュータが1行ずつコードを読んで実行するため、繰り返し処理が多いほど時間がかかります。
たとえば、100万個のデータを1つずつ処理する場合を想像してみてください。
郵便配達員が1軒ずつ手紙を届けるようなものです。
1軒なら問題ないですが、100万軒となると大変ですよね。
よくある遅いコードの例
以下のようなコードを書いたことはありませんか?
# 遅い例:リストに要素を1つずつ追加
result = []
for i in range(1000000):
result.append(i * 2)
このコードは動きますが、要素数が増えると処理時間が急激に長くなります。
実際に計測すると、100万要素で約0.1秒かかることもあります。
一見速そうですが、これが何度も実行されると、全体の処理時間に大きく影響します。
今すぐ使える!7つの高速化テクニック
それでは、実践的な高速化テクニックを見ていきましょう。
どれも簡単に使えるものばかりなので、ぜひ試してみてください。
1. リスト内包表記を使う
最も簡単で効果的な方法がリスト内包表記です。
# 高速な例:リスト内包表記
result = [i * 2 for i in range(1000000)]
先ほどの例と同じ処理ですが、約30%速くなります。
なぜ速いのかというと、Pythonの内部で最適化されているからです。
料理で例えると、材料を1つずつ切るのではなく、まとめて処理するようなイメージです。
2. map関数を活用する
単純な変換処理なら、map()
関数も有効です。
# map関数を使った例
def double(x):
return x * 2
result = list(map(double, range(1000000)))
map()
は、関数を各要素に適用する専用の道具です。
特に既存の関数を適用する場合は、リスト内包表記より速いことがあります。
3. NumPyで配列処理を高速化
数値計算が多い場合は、NumPyが圧倒的に速いです。
import numpy as np
# NumPyを使った例
arr = np.arange(1000000)
result = arr * 2
NumPyは数値計算に特化したライブラリで、C言語で実装されています。
そのため、純粋なPythonより10倍以上速いこともあります。
4. ジェネレータで メモリを節約
すべての結果を一度に必要としない場合は、ジェネレータが便利です。
# ジェネレータ式の例
result = (i * 2 for i in range(1000000))
# 必要な時だけ値を取り出す
for value in result:
if value > 100:
print(value)
break
ジェネレータは、必要になるまで計算を遅らせます。
コンビニの弁当のように、注文があってから作るイメージです。
5. 組み込み関数を使いこなす
Pythonの組み込み関数は、C言語で実装されているため高速です。
# sum()を使った例
numbers = range(1000000)
total = sum(numbers) # for文より速い
# any()を使った例
data = [False, False, True, False]
has_true = any(data) # 1つでもTrueがあるか確認
車輪の再発明をせず、既存の道具を使うことが大切です。
6. 不要な処理を減らす
ループ内で同じ計算を繰り返さないようにしましょう。
# 悪い例:ループ内で同じ計算を繰り返す
result = []
for i in range(10000):
result.append(i * len(data) * 3.14) # len(data)を毎回計算
# 良い例:事前に計算しておく
data_length = len(data)
constant = data_length * 3.14
result = []
for i in range(10000):
result.append(i * constant)
レストランで毎回レシピを確認するより、覚えておく方が効率的ですよね。
7. itertools モジュールを活用
複雑な繰り返し処理には、itertools
モジュールが便利です。
import itertools
# 組み合わせを生成
items = ['A', 'B', 'C']
combinations = list(itertools.combinations(items, 2))
# [('A', 'B'), ('A', 'C'), ('B', 'C')]
# 無限ループも効率的に
for i in itertools.count(start=1, step=2):
if i > 100:
break
print(i) # 1, 3, 5, 7...
専門的な道具を使うことで、複雑な処理も簡潔に書けます。
実際の処理速度を比較してみよう
では、実際にどれくらい速くなるのか見てみましょう。
import time
import numpy as np
# 測定用のデータ
n = 1000000
# 通常のfor文
start = time.time()
result1 = []
for i in range(n):
result1.append(i * 2)
print(f"通常のfor文: {time.time() - start:.3f}秒")
# リスト内包表記
start = time.time()
result2 = [i * 2 for i in range(n)]
print(f"リスト内包表記: {time.time() - start:.3f}秒")
# NumPy
start = time.time()
result3 = np.arange(n) * 2
print(f"NumPy: {time.time() - start:.3f}秒")
私の環境での実行結果:
- 通常のfor文: 0.103秒
- リスト内包表記: 0.072秒
- NumPy: 0.008秒
NumPyは通常のfor文の約13倍も速いことがわかります。
使い分けのポイント
高速化テクニックは状況に応じて使い分けることが大切です。
データ量による選択
- 1000件以下: どの方法でも大差ない
- 1万〜10万件: リスト内包表記やmap()を検討
- 100万件以上: NumPyやジェネレータを積極的に使用
処理内容による選択
- 単純な変換: リスト内包表記
- 数値計算: NumPy
- 条件分岐が多い: 通常のfor文(可読性重視)
- メモリが心配: ジェネレータ
まとめ
Pythonのfor文を高速化する方法をご紹介しました。
重要なポイントをおさらいすると、このようになります。
- リスト内包表記は手軽で効果的
- NumPyは数値計算で圧倒的に速い
- 組み込み関数を積極的に活用する
- ジェネレータでメモリを節約できる
- 状況に応じて使い分けることが大切
これらのテクニックを使えば、処理時間を大幅に短縮できます。
まずは自分のコードで試してみて、どれくらい速くなるか確認してみてください。
小さな改善の積み重ねが、大きな効率化につながりますよ。
著者について

とまだ
フルスタックエンジニア
Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。
著者の詳細を見る →