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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

4765閲覧

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

gunmed

総合スコア55

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/02/24 06: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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

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

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

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

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

投稿2019/02/24 09:51

otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gunmed

2019/02/28 12:49

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

0

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

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

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

投稿2019/02/24 07:34

fu7mu4

総合スコア1088

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gunmed

2019/02/24 07:59

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

0

ベストアンサー

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

  • func1

コンパイルを行わないで100回マッチングを試みます。

  • func2

前以てコンパイルしたパターンを用い、100回マッチングを試みます。

  • func3

100回、コンパイルしてからマッチングします。

Python

1import re 2import timeit 3 4 5def func1(): 6 for _ in range(100): 7 re.search(r'\d+', 'hoge123fuga') 8 9def func2(): 10 regex = re.compile(r'\d+') 11 12 for _ in range(100): 13 regex.search('hoge123fuga') 14 15def func3(): 16 for _ in range(100): 17 regex = re.compile(r'\d+') 18 regex.search('hoge123fuga') 19 20 21for func in [func1, func2, func3]: 22 print(func) 23 print(timeit.timeit(lambda: func(), number=10000))

実行結果 Wandbox

stdout

1<function func1 at 0x7f8602783e18> 21.799713782966137 3<function func2 at 0x7f86012d0950> 40.7829366624355316 5<function func3 at 0x7f86012d09d8> 61.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 07:34

編集2019/02/24 08:52
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gunmed

2019/02/24 08:04

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問