在经常调用的函数中编译正则表达式

时间:2015-06-06 23:42:17

标签: python regex function scope

假设我有一个函数,它使用正则表达式在字符串中搜索多个模式:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{   
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

        // Write to log
        NSLog(@"Trying to change view...");

    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    { 

    }];

    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

现在假设这个函数将被调用数十万次,并且它不是一个简单的例子。是否a)是否正在函数内完成正则表达式编译,即在每次函数调用时调用编译操作是否存在效率成本(或者是否从缓存中重用?)和b)如果存在,将会是什么一种避免这种开销的推荐方法?

一种方法是将函数传递给已编译的正则表达式对象列表:

import re
def get_patterns(string):
    """
    Takes a string and returns found groups
    of numeric and alphabetic characters.

    """
    re_digits = re.compile("(\d+)")
    re_alpha = re.compile("(?i)([A-Z]+)")
    digits = re_digits.findall(string)
    alpha = re_alpha.findall(string)
    return digits, alpha

get_patterns("99 bottles of beer on the wall")
(['99'], ['bottles', 'of', 'beer', 'on', 'the', 'wall'])

但我不喜欢这种方法如何将正则表达式从依赖函数中分离出来。

更新:根据Jens&#39;建议我已经进行了快速计时检查,并且在函数的默认参数中进行编译确实相当快(~30%):

re_digits = re.compile("(\d+)")
re_alpha = re.compile("(?i)([A-Z]+)")
def get_patterns(string, [re_digits, re_alpha]):

3 个答案:

答案 0 :(得分:4)

一种解决方案是使用默认参数,因此它们只编译一次:

import re
def get_patterns(string, re_digits=re.compile("(\d+)"), re_alpha=re.compile("(?i)([A-Z]+)")):
    """
    Takes a string and returns found groups
    of numeric and alphabetic characters.

    """
    digits = re_digits.findall(string)
    alpha = re_alpha.findall(string)
    return digits, alpha

现在你可以打电话给它:

get_patterns(string)

答案 1 :(得分:1)

您可以使用Python的timeit(或herehere)功能来衡量执行时间。

如果您想避免重复编译这些正则表达式,请尝试将它们初始化为全局:

import re

_re_digits = re.compile("(\d+)")
_re_alpha = re.compile("(?i)([A-Z]+)")

def get_patterns(string): 
    digits = _re_digits.findall(string)
    alpha = _re_alpha.findall(string)
    return (digits, alpha)

答案 2 :(得分:1)

有趣的事实:您可以在Python中设置和获取函数的属性,就像任何其他对象一样。所以另一个避免全局变量并且只编译正则表达式的解决方案就是这样的:

  $('#container-rpm').highcharts(Highcharts.merge(gaugeOptions, {
            series: [{
                data: {{data}},
            }]
        }));

另一个解决方案是使用闭包:

def get_patterns(string):
    f = get_patterns
    return f.digits.findall(string), f.alpha.findall(string)

get_patterns.digits = re.compile("(\d+)")
get_patterns.alpha = re.compile("(?i)([A-Z]+)")