4

私は Doug Hellman の「The Python Standard Library by Example」を読んでいて、これに出くわしました:

「1.3.2 式のコンパイル re には、正規表現をテキスト文字列として操作するためのモジュールレベルの関数が含まれていますが、プログラムで頻繁に使用する式をコンパイルする方が効率的です。」

なぜそうなるのかについて、私は彼の説明を理解できませんでした。彼は、「モジュール レベルの関数はコンパイルされた式のキャッシュを維持する」と述べ、「キャッシュのサイズ」が制限されているため、「コンパイルされた式を直接使用すると、キャッシュ ルックアップのオーバーヘッドが回避される」と述べています。

プログラムが頻繁に使用する正規表現をコンパイルする方が効率的である理由と、このプロセスが実際にどのように機能するかについて、誰かが説明してくれるか、よりよく理解できる説明を教えていただければ幸いです。

4

3 に答える 3

9

うーん。変ですね。これまでの私の知識 (他の情報源の中でも、この質問から得られたもの) は、私の最初の答えを示唆しています。


最初の答え

Python は、使用した最後の 100 個の正規表現をキャッシュするため、それらを明示的にコンパイルしなくても、使用するたびに再コンパイルする必要はありません。

ただし、2 つの欠点があります。100 個の正規表現の制限に達すると、キャッシュ全体が削除されるため、101 個の異なる正規表現を続けて使用すると、毎回それぞれが再コンパイルされます。まあ、それはかなりありそうもないですが、それでも.

次に、正規表現がすでにコンパイルされているかどうかを調べるために、インタープリターは毎回キャッシュ内の正規表現を検索する必要がありますが、これには少し余分な時間がかかります (ただし、辞書検索は非常に高速であるため、それほど時間はかかりません)。

したがって、正規表現を明示的にコンパイルすると、この余分な検索手順を回避できます。


アップデート

私はいくつかのテストを行いました(Python 3.3):

>>> import timeit
>>> timeit.timeit(setup="import re", stmt='''r=re.compile(r"\w+")\nfor i in range(10):\n r.search("  jkdhf  ")''')
18.547793477671938
>>> timeit.timeit(setup="import re", stmt='''for i in range(10):\n re.search(r"\w+","  jkdhf  ")''')
106.47892003890324

したがって、キャッシュが行われていないように見えます。おそらく、それtimeit.timeit()は実行される特別な条件の癖でしょうか?

一方、Python 2.7 では、違いはそれほど目立ちません。

>>> import timeit
>>> timeit.timeit(setup="import re", stmt='''r=re.compile(r"\w+")\nfor i in range(10):\n r.search("  jkdhf  ")''')
7.248294908492429
>>> timeit.timeit(setup="import re", stmt='''for i in range(10):\n re.search(r"\w+","  jkdhf  ")''')
18.26713670282241
于 2013-02-07T16:27:34.510 に答える
4

彼が言おうとしているのは、ループの内側ではなく、ループの外側で正規表現をコンパイルする必要があるということだと思います。その後、ループ内でコンパイル済みのコードを実行できます。

それ以外の:

while true: 
    result = re.match('A', str)

あなたは置くべきです:

regex = re.compile('A')
while true:
    result = regex.match(str)

基本的re.match(pattern, str)に、コンパイルとマッチングのステップを組み合わせます。ループ内で同じパターンをコンパイルするのは非効率的であるため、ループの外側に持ち上げる必要があります。

正しい理由については、ティムの答えを参照してください。

于 2013-02-07T16:24:00.997 に答える
0

作者は、モジュールの制限されたサイズの内部キャッシュにまだ保持されている以前にコンパイルされたバージョンを頼りにするよりも、正規表現をコンパイルして保存する方が効率的だと言っているように思えます。これはおそらく、それらをコンパイルするのにかかる労力に加えて、最初に発生しなければならない余分なキャッシュルックアップオーバーヘッドが、クライアントが単にそれらを格納するよりも大きいためです。

于 2013-02-07T16:36:59.093 に答える