LoginSignup
1
1

More than 5 years have passed since last update.

re.compileしたオブジェクトがre.matchのパターンに使える件について

Last updated at Posted at 2015-05-09

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"と明記されている。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1