3

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

_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

4 回答 4

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 中的惰性属性装饰器提出问题的原因,您可能也会对此感兴趣;除非您发现自己经常重复这种模式,否则我不会为此烦恼。)

于 2013-07-04T02:29:16.657 回答
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 ...
于 2013-07-04T02:28:29.440 回答
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

但老实说,我通常在这一点上切换到一个类。

于 2013-07-04T02:59:07.670 回答
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)
于 2013-07-04T06:36:33.327 回答