Python速度比較 regex vs startswith vs str[:num]
はじめに
Ptyhonである文字列の前方一致を判定する方法はいくつかある。
その中で代表的な以下の3つの速度比較を行う。
- 正規表現
- startswith
- str[:word_length] == word
測定方法
環境
以下の実行環境で実施する
| 項目 | 値 |
|---|---|
| Python Version | 3.8.2 |
| OS | Ubuntu 20.04 |
プログラム
以下のプログラムを基準にして動作を確認する。なお各変数と各関数の役割は以下の通りである。
計測したい特性に応じて変数を変化させる。
| 変数/関数 | 説明 |
|---|---|
| time_logging | 時間を計測するためのデコレータ |
| compare_regex | 引数の文字列のリストのそれぞれを正規表現で比較する |
| compare_startswith | 引数の文字列のリストのそれぞれをstartswithメソッドで比較する |
| compare_str | 引数の文字列のリストのそれぞれの最初の文字列がtarget_wordと等しいかを比較する |
| target_word | 比較対象となる文字列 |
| match_word |
target_wordとマッチする文字列のプレフィックス |
| not_match_word |
target_wordとマッチしない文字列のプレフィックス |
| compare_word_num | 比較する文字列を総数 |
| compare_func | 測定する関数 |
| main | 呼び出される関数 |
import re
import time
def time_logging(func):
def deco(*args, **kwargs):
stime = time.time()
res = func(*args, **kwargs)
etime = time.time()
print(f'Finish {func.__name__}. Takes {round(etime - stime, 3)}s.', flush=True)
return res
return deco
@time_logging
def compare_regex(compare_words):
pattern = re.compile(f'^{target_word}')
for word in compare_words:
if pattern.match(word):
pass
@time_logging
def compare_startswith(compare_words):
for word in compare_words:
if word.startswith(target_word):
pass
@time_logging
def compare_str(compare_words):
length = len(target_word)
for word in compare_words:
if word[:length] == target_word:
pass
target_word = f'foo'
match_word = f'{target_word}'
not_match_word = f'bar'
compare_word_num = 100_000_000
match_rate = 50
compare_func = compare_regex
def main():
compare_words = []
for index in range(compare_word_num):
if index % 100 <= match_rate:
compare_words.append(f'{match_word}_{index}')
else:
compare_words.append(f'{not_match_word}_{index}')
compare_func(compare_words)
if __name__ == '__main__':
main()
パラメータ
比較対象の文字列の長さで実行速度の傾向が変わる可能性があるため、
target_wordを5文字, 10文字, 50文字, 100文字, 500文字と変化させたときのcompare_regex, compare_startswith, compare_strの実行速度をそれぞれ計測する。
測定
単位(秒)
| 関数\文字数 | 5 | 10 | 50 | 100 | 500 |
|---|---|---|---|---|---|
| compare_regex | 11.617 | 12.044 | 16.126 | 18.837 | 66.463 |
| compare_startswith | 6.647 | 6.401 | 6.241 | 6.297 | 6.931 |
| compare_str | 5.941 | 5.993 | 4.87 | 5.449 | 8.875 |
考察
速度的には、あらゆる文字数でstartswithまたは、str[:word_length]で実装すべきである。比較対象の文字列の影響をもっとも受けないstartswithがもっともおすすめ。
また可読性という観点でも一番好き。
