reモジュールの隅をつつく話
re_spam.py
# -*- coding: utf-8 -*-
import re
re.match("spa*m", "spam") # わかる
spam = re.compile("spa*m")
spam.match("spaaaaaaaam") # わかる
re.match(spam, "spaaaam") # なぜか動く
上記のようにre.compileで得られた正規表現オブジェクトがre.matchのパターンに使える。
patternとして渡されたのが正規表現オブジェクトかどうか一応判定しているようだ。
この方法、何かメリットがあるのだろうか?処理速度はre.matchを使うより遅い。
変遷
こちらはPython-1.5.2のソース(抜粋)
re.py
def _cachecompile(pattern, flags=0):
key = (pattern, flags)
try:
return _cache[key]
except KeyError:
pass
value = compile(pattern, flags)
if len(_cache) >= _MAXCACHE:
_cache.clear()
_cache[key] = value
return value
def match(pattern, string, flags=0):
return _cachecompile(pattern, flags).match(string)
def compile(pattern, flags=0):
"Compile a regular expression pattern, returning a RegexObject."
groupindex={}
code=pcre_compile(pattern, flags, groupindex)
return RegexObject(pattern, flags, code, groupindex)
特にチェックはない。
続いてPython-2.0.1のsre.py(抜粋)
sre.py
def match(pattern, string, flags=0):
"""Try to apply the pattern at the start of the string, returning
a match object, or None if no match was found."""
return _compile(pattern, flags).match(string)
def _compile(*key):
# internal: compile pattern
p = _cache.get(key)
if p is not None:
return p
pattern, flags = key
if type(pattern) not in sre_compile.STRING_TYPES:
return pattern
try:
p = sre_compile.compile(pattern, flags)
except error, v:
raise error, v # invalid expression
if len(_cache) >= _MAXCACHE:
_cache.clear()
_cache[key] = p
return p
コンパイルできる文字列でなければpatternをそのまま返しているようだ。
そしてPython-2.7.9のre.py(抜粋)
re.py
def match(pattern, string, flags=0):
"""Try to apply the pattern at the start of the string, returning
a match object, or None if no match was found."""
return _compile(pattern, flags).match(string)
def _compile(*key):
# internal: compile pattern
pattern, flags = key
bypass_cache = flags & DEBUG
if not bypass_cache:
cachekey = (type(key[0]),) + key
try:
p, loc = _cache[cachekey]
if loc is None or loc == _locale.setlocale(_locale.LC_CTYPE):
return p
except KeyError:
pass
if isinstance(pattern, _pattern_type):
if flags:
raise ValueError('Cannot process flags argument with a compiled pattern')
return pattern
if not sre_compile.isstring(pattern):
raise TypeError, "first argument must be string or compiled pattern"
try:
p = sre_compile.compile(pattern, flags)
except error, v:
raise error, v # invalid expression
if not bypass_cache:
if len(_cache) >= _MAXCACHE:
_cache.clear()
if p.flags & LOCALE:
if not _locale:
return p
loc = _locale.setlocale(_locale.LC_CTYPE)
else:
loc = None
_cache[cachekey] = p, loc
return p
patternが文字列であるかどうかの他にコンパイル済みかどうかもチェックしているし、"first argument must be string or compiled pattern"と明記されている。