昂贵的预先计算的数据仅与一个功能相关

时间:2013-07-04 02:24:10

标签: python

我发现自己经常编写这样的代码:

_munge_text_re = re.compile("... complicated regex ...")
def munge_text(text):
    match = _munge_text_re.match(text)
    ... do stuff with match ...

只有munge_text使用_munge_text_re,因此最好以某种方式将其设置为函数本地,但如果我在re.compile内移动def行,那么它将在每次调用函数时进行评估,从而无法编译正则表达式。

有没有办法让_munge_text_re本地化为munge_text,同时仍然只评估其初始化程序一次?单个评估不需要在模块加载时进行;第一次调用munge_text就足够了。

该示例使用正则表达式,并且我需要它的大部分时间用于正则表达式,但它可能是实例化成本高昂的任何数据(因此您不希望每次调用该函数时都这样做)并在程序的生命周期内修复。还会想到ConfigParser个实例。

额外的功劳:由于进入这里过于繁琐的原因,我当前的项目需要极端的向后兼容性,因此在Python 2.0 中运行的解决方案将比不支持的解决方案更好。

4 个答案:

答案 0 :(得分:3)

现在它有状态,只需为它做一个类:

class TextMunger(object):

    def __init__(self, regex):
        self._pattern = regex
        self._munge_text_re = None

    def __call__(self, text):
        if self._munge_text_re is None:
            self._munge_text_re = re.compile(self._pattern)

        match = self._munge_text_re.match(text)
        # ... do stuff with match ...

munge_text = TextMunger("... complicated regex ...")

# The rest of your code stays the same

如果您不知道,类上的__call__方法意味着可以像调用函数那样调用对象,因此您可以像以前一样继续使用munge_text(text)

(这种问题实际上导致了我对Python中lazy property decorator的疑问,这可能也会引起你的兴趣;除非你发现自己重复这种模式,否则我不会打扰它。)

答案 1 :(得分:1)

_munge_text_re = None
def munge_text(text):
    global _munge_text_re
    _munge_text_re = _munge_text_re or re.compile("... complicated regex ...")
    match = _munge_text_re.match(text)
    ... do stuff with match ...

答案 2 :(得分:0)

另一种方法 - 我只提到信息,而不是因为我在生产中使用它,所以我将社区维基这个 - 将状态存储在函数本身中。您可以使用hasattr或抓住AttributeError

def munge1(x):
    if not hasattr(munge1, 'val'):
        print 'expensive calculation'
        munge1.val = 10
    return x + munge1.val

def munge2(x):
    try:
        munge2.val
    except AttributeError:
        print 'expensive calculation'
        munge2.val = 10
    return x + munge2.val

之后

>>> munge1(3)
expensive calculation
13
>>> munge1(3)
13
>>> munge2(4)
expensive calculation
14
>>> munge2(4)
14

但说实话,我现在通常会换班。

答案 3 :(得分:0)

我想你可以做以下事情:

def munge_text(text):
    global munge_text
    _munge_text_re = re.compile("... complicated regex ...")
    def t(text):
       match = _munge_text_re.match(text)
       ... do stuff with match ...
    munge_text = t
    return t(text)