質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

pythonの正規表現のre.compileの理解が正しいか判断してほしい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 6,747

gunmed

score 55

こんにちは。pythonを勉強しているプログラミング初心者です。
re.compileを理解しようとして公式などを色々調べて、以下のようなコードを作りました。

import re

row = re.compile(r'\d+')
result = row.search('I have 2000 yen')
print(result)

#<re.Match object; span=(7, 11), match='2000'>

コンパイルというのを初めて聞いたので、調べてみると機械語に翻訳することだと知りました。
また、pythonはコンパイラ型言語ではないので、コンパイルする必要がなく、一行ずつ翻訳するらしいです。

今回のre.compileは正規表現をあらかじめコンパイルするということで、
re.search(r'\d+', 'I have 2000 yen')と本来は書くところを
row.search('I have 2000 yen')と短縮して書くことができる。

re.compileはpatternをコンパイルすることで処理する速度が早くなるというのがメリットであり、\d+というpatternを多く使うなら
あらかじめコンパイルしておくことで処理速度が早くなる。だから、別に多く使わないならre.compileを積極的に使う必要はない。

上記のように理解したのですが、コンパイルというのを初めて聞いたので、確認のため質問させていただきました。

mac 10.14.1
visual studio code

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

実際に計測してみると良いです。

  • func1
    コンパイルを行わないで100回マッチングを試みます。
  • func2
    前以てコンパイルしたパターンを用い、100回マッチングを試みます。
  • func3
    100回、コンパイルしてからマッチングします。
import re
import timeit


def func1():
    for _ in range(100):
        re.search(r'\d+', 'hoge123fuga')

def func2():
    regex = re.compile(r'\d+')

    for _ in range(100):
        regex.search('hoge123fuga')

def func3():
    for _ in range(100):
        regex = re.compile(r'\d+')
        regex.search('hoge123fuga')


for func in [func1, func2, func3]:
    print(func)
    print(timeit.timeit(lambda: func(), number=10000))

実行結果 Wandbox

<function func1 at 0x7f8602783e18>
1.799713782966137
<function func2 at 0x7f86012d0950>
0.7829366624355316
<function func3 at 0x7f86012d09d8>
1.7352472953498363

ある程度測定誤差は出ますが、 func2 < func1 ≒ func3 であることが分かります。

re.compileを使わなかったときも、実際には内部的にコンパイルが走っています。
それはfunc1とfunc3の実行時間がほとんど同じことからも明らかです。

ですので、単発で使う正規表現をわざわざコンパイルするメリットはほとんどありません。

別に多く使わないならre.compileを積極的に使う必要はない。

この主張は概ね正しいように思います。

追記

私の説明が厳密にはリファレンスに反することに気付きました。

 re.compile() に渡されてコンパイルされた最新のパターンと、モジュールレベルのマッチング関数はキャッシュされるので、一度に少しの正規表現しか使わないプログラムは正規表現のコンパイルについて心配する必要はありません。

引用元: Python 標準ライブラリ » re — 正規表現操作

実測したコードで用いた一種類の正規表現は、この説明に依るとキャッシュされている筈です。

ですので、実行時間の差は正規表現のコンパイルそれ自体に依るものでは無く、
キャッシュの検索、つまりre.compileの呼び出しが影響しているのだと考えられます。

『直前にre.compileを潜らせるメリットは薄い』と言う本筋の主張には変わりないです。

コンパイル型言語とインタプリタ型言語

特に初心者向けの説明で散見する表現ですが、個人的には適切ではない分類方法だと思います。

まず、「コンパイラ言語」「スクリプト言語」というのは俗称であって、正式な分類ではありません。確かに、「コンパイル型として実装されることが多い言語」「インタプリタで実装されることが多い言語」というのがありますが、それはあくまで相対的なものでしかありません。

teratail - コンパイル言語とスクリプト言語の違い - maisumakunさんの回答

近年の開発環境などでは、コンパイル(ビルド)して実行、というような手続きを1命令で行えるものも増えている。そして、インタプリタでも実行時コンパイラなどの技術の利用がさかんになってきており、古典的な意味での「コンパイラ」と「インタプリタ」の中間的な性質のツール(プログラム)も増えてきているので、「コンパイラ言語 / インタプリタ言語」という、以前よく行われた対比は、あまり意味を持たない場合も増えてきている。

Wikipedia - コンパイラ

コンパイルという言葉の持つ意味が広すぎるので、
単に『前以てちょっと処理してるんだなぁ』くらいの感覚で良いと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/24 17:04

    回答ありがとうございます。
    実際に計測できるのを知らなかったので、とてもためになりました。
    コンパイル型言語とインタプリタ型言語の表現について、訂正ありがとうございます。
    用語の正確さは大切だと思うのですが、なかなか理解しづらい概念なので、URLを参考に整理しようとと思います。アドバイスも参考になりました。ありがとうございました。

    キャンセル

+1

話はだいたいあっていますが、用語は正しくありません。

公式には、「re.compileは正規表現パターンを正規表現オブジェクトにコンパイルします。」と説明されていますが、r'\d' であらわされている正規表現パターンをpythonの内部表現である正規表現オブジェクトに変換するというように考えられるでしょう。
生成された正規表現オブジェクトを使ってそのメソッド呼び出しで正規表現検索などができるわけです。

https://docs.python.jp/3/library/re.html#module-contents

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/24 16:59

    回答ありがとうございます。
    なるほど、パターンを正規表現オブジェクトに変換し、それを呼び出しているのですね。
    理解が深まりました。

    キャンセル

+1

コンパイルというのは、機械語に翻訳するだけではありません。

一般には、「文字列(文字列データや、文字列で書かれたプログラム)を内部表現に変換すること」でしょうか。

端末から数字を入力して、その値をループの中で使う場合、入力した数字の文字列を、ループの中で毎回int()して使うのと、ループの前にint()して変数に代入し、ループの中ではその変数を使うのとでは、ループの回数が膨大な場合に、実行時間に差が出ます。100回、1000回くらいだと、あまり差は無いかと。
それと同じようなことです。

(数字文字列を数値に変換することは、あまり「コンパイル」とは言いませんが)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/28 21:49

    回答ありがとうございます。
    気づくのが遅れてしまいすみません。
    例がとてもわかりやすく、参考になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る