re.sub の使い方

  • May 08, 2007 08:25

djangoのコード読みから

Pythonの正規表現の置き換えに

re.sub(pattern, repr, string)

というのがあるのですが、これは stringにマッチするパターンをreprで置き換えるものです。

In [1]: re.sub('bar', ' foo ', 'barbarbar')
Out[1]: ' foo  foo  foo '

あまり使わないのでreprは文字列だけかと思ったら マッチしたオブジェクトを引数に文字列を返すcallableのオブジェクトでOKらしいです。知らなかった。(僕が知らなかっただけで基本みたいです)

In [2]: def repl_func(a):
 .....:     return " || %s %s || " % (a.group(), a.group(1))
 .....:

In [3]: re.sub(re.compile(r'b(.)r'), repl_func, 'barbarbar')
Out[3]: ' || bar a ||  || bar a ||  || bar a || '

Djangoではdjango.core.urlresolversにあるreverse_helper関数で使われていて

>>> reverse_helper(re.compile('^places/(\d+)/$'), 3)
'places/3/'

のようにパターンと引数から逆引きしてURLを割り出すことができます。

中身は

result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), regex.pattern)


class MatchChecker(object):
    "Class used in reverse RegexURLPattern lookup."
    def __init__(self, args, kwargs):
        self.args, self.kwargs = args, kwargs
        self.current_arg = 0

    def __call__(self, match_obj):
        ### いろいろ処理
        return str(value)

となっていて、result=re.subの中でMatchCheckerクラスをインスタンス化して、re.subに評価されるときにはcallableオブジェクトとして呼ばれています。