我在 YAML 配置文件中定义了一个正则表达式。
为了方便起见,我将在这里使用字典:
rule_1 = {
'kind': 'regex',
'method': 'match',
'args': None,
'kwargs': {
'pattern': "[a-z_]+",
'flags': re.X,
'string': 's_test.log',
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在函数中解析该规则。
如果我们假设这些值不会改变,那么我可以做这样的事情。
导入模块:
import re
from operator import methodcaller
from functools import partial
Run Code Online (Sandbox Code Playgroud)
我下面的第一个函数能够适应所使用的正则表达式方法的变化:
def rule_parser_re_1(*, kind, method, args=None, kwargs=None):
if args is None: args = []
if kwargs is None: kwargs = {}
mc = methodcaller(method, **kwargs)
return mc(re)
Run Code Online (Sandbox Code Playgroud)
它按预期工作:
>>> rule_parser_re_1(**rule_1)
<re.Match object; span=(0, 6), match='s_test'>
Run Code Online (Sandbox Code Playgroud)
现在,假设在定义配置字典时我没有要解析的字符串。
例如,假设它是文件中的特定行,只能在运行时访问。
myfile = """
first line
second line
third line
"""
io_myfile = io.StringIO(myfile)
content = io_myfile.readlines()
Run Code Online (Sandbox Code Playgroud)
我的第二条规则,其中“line_number”(即 an int)替换“string”(即 a str)。
rule_2 = {
'kind': 'regex',
'method': 'match',
'args': None,
'kwargs': {
'pattern': "[a-z_]+",
'flags': re.X,
'line_number': 2,
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是我应该能够通过定义一个偏rule_parser_re函数来解决这个问题。这样的函数应该像原来的函数一样使用patternand调用flags,但不使用string。
我想出了以下功能:
def rule_parser_re_2(*, kind, method, args=None, kwargs=None):
if args is None: args = []
if kwargs is None: kwargs = {}
if kind == 'regex' and method == 'match':
pa = partial(re.match, pattern=kwargs['pattern'], flags=kwargs['flags'])
return pa
Run Code Online (Sandbox Code Playgroud)
这似乎也可以正常工作:
>>> r2 = rule_parser_re_2(**rule_2)
>>> r2(string=content[2])
<re.Match object; span=(0, 6), match='second'>
Run Code Online (Sandbox Code Playgroud)
虽然,我看到上述实现有两个可维护性问题:
if语句,它迫使我为re我想要支持的每个方法修改函数;我的目标/怀疑:
functools.partial()和operator.methodcaller()对工作的合适的工具?谢谢!
由于您的第二个模式与\xe2\x80\x99t 的签名不匹配re.match(等),因此您需要编写自己的函数。它可以使用带有命名参数的包装函数来适应接口(尽管这涉及修复您发明的line_number参数的位置,如果您关心的话args)。它还可以使用getattr,这相当于 的某些简单用法operator.methodcaller:
def rule2(kind,method,args,kwargs):\n return _rule2(getattr(re,method),*args or (),**kwargs or {})\ndef _rule2(f,pattern,line_number,flags):\n return lambda content: f(pattern,content[line_number],flags)\nRun Code Online (Sandbox Code Playgroud)\n请注意,这content是保留的参数,因为只有行号会使文件内容未知;由于它不是底层函数的直接参数,partial因此 \xe2\x80\x99 不是正确的工具。
| 归档时间: |
|
| 查看次数: |
183 次 |
| 最近记录: |