我的目标是创建一个非常简单的模板语言.目前,我正在使用值替换变量,如下所示:
这个输入:
网络
应该产生这个输出:
Web这是一个测试变量
我有它的工作.但是看着我的代码,我在相同的字符串上运行多个相同的正则表达式 - 这只是冒犯了我的效率感.必须有更好,更Pythonic的方式.(这是真正冒犯的两个"while"循环.)
这确实通过了单元测试,所以如果这是愚蠢的过早优化,请告诉我 - 我愿意放手.在文档中可能有许多这些变量定义和用法,但不是数百个.但我怀疑(对其他人)显而易见的改善方法,我很好奇StackOverflow人群会想出什么.
def stripMatchedQuotes(item):
MatchedSingleQuotes = re.compile(r"'(.*)'", re.LOCALE)
MatchedDoubleQuotes = re.compile(r'"(.*)"', re.LOCALE)
item = MatchedSingleQuotes.sub(r'\1', item, 1)
item = MatchedDoubleQuotes.sub(r'\1', item, 1)
return item
def processVariables(item):
VariableDefinition = re.compile(r'<%(.*?)=(.*?)%>', re.LOCALE)
VariableUse = re.compile(r'<%(.*?)%>', re.LOCALE)
Variables={}
while VariableDefinition.search(item):
VarName, VarDef = VariableDefinition.search(item).groups()
VarName = stripMatchedQuotes(VarName).upper().strip()
VarDef = stripMatchedQuotes(VarDef.strip())
Variables[VarName] = VarDef
item = VariableDefinition.sub('', item, 1)
while VariableUse.search(item):
VarName = stripMatchedQuotes(VariableUse.search(item).group(1).upper()).strip()
item = VariableUse.sub(Variables[VarName], item, 1)
return item
Run Code Online (Sandbox Code Playgroud) 假设我有一个使用正则表达式在字符串中搜索多个模式的函数:
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'])
Run Code Online (Sandbox Code Playgroud)
现在假设这个函数将被调用数十万次,这不是一个简单的例子。a) 是否在函数内完成正则表达式编译是否重要,即在每次函数调用时调用编译操作是否存在效率成本(或者它是否从缓存中重用?)和 b) 如果有,会是什么避免这种开销的推荐方法?
一种方法是向函数传递已编译的正则表达式对象列表:
re_digits = re.compile("(\d+)")
re_alpha = re.compile("(?i)([A-Z]+)")
def get_patterns(string, [re_digits, re_alpha]):
Run Code Online (Sandbox Code Playgroud)
但我不喜欢这种方法如何将正则表达式与依赖函数分离。
更新:根据 Jens 的建议,我运行了一个快速的计时检查,并且在函数的默认参数中进行编译确实快了很多(~30%):
def get_patterns_defaults(string,
re_digits=re.compile("(\d+)"),
re_alpha=re.compile("(?i)([A-Z]+)")
):
"""
Takes a string and returns found groups …
Run Code Online (Sandbox Code Playgroud)