🐲

Pythonを高速化するための簡単テクニック集【AI時代の必須知識】

に公開

AI時代ということで、みなさんPythonを使っていますよね。

Pythonは書きやすく、ライブラリも豊富でAI開発に非常に適しています。ただし、CやRustなどのコンパイル言語と比べると、どうしても処理速度で劣ってしまいます。

もちろん、CythonやmypycのようにPythonコードを高速化する手段もありますが、すべてのケースに万能というわけではありません。

そこで本記事では、Pythonコードを簡単に高速化できるテクニックを厳選して紹介します!

1. 組み込み関数を使用する

まさか、リスト内に値があるか確認するのに for 文を使っていませんよね?

import time

lst = list(range(10_000_000))
target = 9999999

# for loop
start = time.time()

found = False
for i in lst:
    if i == target:
        found = True
        break

end = time.time()
in_time = end - start
print(f"for:  {in_time:.6f} 秒") # for:  0.240200 秒

組み込みの in を使えば、数倍高速になります。in は内部的にCで実装された最適化ループを使用しているためです。

# x in list
start = time.time()
found = target in lst
end = time.time()
in_time = end - start
print(f"in:  {in_time:.6f} 秒") # in:  0.048049 秒

さらに list を set に変換すると、桁違いに高速になります。set はハッシュテーブルを使って探索するためです。
※ただし set() への変換にはコストがかかるため、何度も検索する場合に有効です。1回きりであれば list のままのほうが速いケースもあります。

# x in set
set_list = set(lst)
start = time.time()

found = target in set_list

end = time.time()
in_time = end - start
print(f"set:  {in_time:.6f} 秒") # set:  0.000022 秒

2. list内包表記を使う。

Pythonでは、for 文よりも内包表記のほうが高速で簡潔です。

# 遅い
start = time.time()

result = []
for i in range(10000):
    result.append(i * 2)

end = time.time()
in_time = end - start
print(f"for:  {in_time:.6f} 秒") # for:  0.000439 秒

# 速い ✅
start = time.time()

result = [i * 2 for i in range(10000)]

end = time.time()
in_time = end - start
print(f"list:  {in_time:.6f} 秒") # list:  0.000203 秒

3. 辞書をインデックス化に使う

データ量が多くなればなるほど、辞書の恩恵は大きくなります。

# 遅い(毎回ループして検索)
for user in users:
    if user["id"] == target_id:
        return user

# 速い ✅(事前に辞書に変換)
user_map = {u["id"]: u for u in users}
return user_map[target_id]

4. 関数のルックアップを変数にキャッシュ

関数名の参照にもコストがかかるため、頻繁に呼び出す場合は一度変数にキャッシュするとわずかに高速化できます。

import math

start = time.time()

for _ in range(1000000):
    math.sqrt(25)

end = time.time()
in_time = end - start
print(f"slow: {in_time:.6f} 秒") # slow: 0.045684 秒

# 速い ✅
start = time.time()

sqrt = math.sqrt
for _ in range(1000000):
    sqrt(25)

end = time.time()
in_time = end - start
print(f"fast: {in_time:.6f} 秒") # fast: 0.040922 秒

5. enumerate() を使う (index付きループが速くて簡潔)

range(len(...)) よりも、enumerate() を使った方が速くて可読性も良いです。

# 遅い
for i in range(len(data)):
    value = data[i]

# 速い ✅
for i, value in enumerate(data):
    ...

最後に

いくつ知っていましたか?

他にも「これ知ってると速くなるよ!」というテクニックがあれば、ぜひコメントで教えてください!

Discussion