我发现自己经常编写这样的代码:
_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 中运行的解决方案将比不支持的解决方案更好。
答案 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)