Python で正規表現を使うとき、こんな2通りの書き方があります。
import re
# 方法A: その場で re.match
if re.match(r'^Endpoint:', line):
...
# 方法B: 事前に re.compile
RE_END = re.compile(r'^Endpoint:')
if RE_END.match(line):
...
見た目は似ていますが、中の仕組みが違うんです。
1. re.match の仕組み
実は re.match(pattern, string)
は 内部で毎回 re.compile(pattern)
を呼んでから .match()
しています。
図にするとこう:
line1 ── re.match("pattern", line1)
└─ re.compile("pattern") # ← ここで毎回コンパイル
└─ .match(line1)
line2 ── re.match("pattern", line2)
└─ re.compile("pattern") # ← また新しく作る
└─ .match(line2)
...
つまり、行を読むたびに「設計図を作って → マッチさせる」ことを繰り返しているイメージです。
2. re.compile(...).match の仕組み
一方で、re.compile
を先に呼んでおけば「設計図」は最初の1回だけ。
その後は .match()
を繰り返すだけで済みます。
RE = re.compile("pattern") # 最初に設計図を1回だけ作る
line1 ── RE.match(line1) # 既に準備済みのパターンを使う
line2 ── RE.match(line2)
line3 ── RE.match(line3)
...
つまり「1回設計 → あとは照合のみ」。大量のテキストを扱うときに高速です。
3. パフォーマンス実験
import re, time
pattern = r'^Endpoint:'
lines = ["Endpoint: U5/D"] * 100_000
# 事前コンパイル
RE = re.compile(pattern)
t0 = time.time()
for ln in lines:
RE.match(ln)
t1 = time.time()
# 毎回 re.match
t2 = time.time()
for ln in lines:
re.match(pattern, ln)
t3 = time.time()
print("precompiled:", t1-t0, "sec")
print("re.match :", t3-t2, "sec")
結果(例):
precompiled: 0.03 sec
re.match : 0.15 sec
→ 事前コンパイルのほうが数倍速い!
4. まとめ:どちらを使うべき?
- レポート解析のように何千行も処理するなら
👉re.compile
で事前に準備して使い回す - 学習用スクリプトや一度きりの判定なら
👉re.match
でもOK(でも癖としてre.compile
を覚えたほうが良い)
💡 ポイント
re.match
は「毎回コンパイル」してからマッチRE = re.compile(...)
は「最初だけコンパイル」して後は使い回す- 大規模処理では 速度差が大きくなる
- 名前を付けて変数に入れておくと、コードの可読性・保守性も向上