在Python中创建动态部分可调用对象

我在 YAML 配置文件中定义了一个正则表达式。

为了方便起见,我将在这里使用字典:

rule_1 = {
    'kind': 'regex',
    'method': 'match',
    'args': None,
    'kwargs': {
        'pattern': "[a-z_]+",
        'flags': re.X,
        'string': 's_test.log',
    }
}

我希望能够在函数中解析该规则。

如果我们假设这些值不会改变,那么我可以做这样的事情。

导入模块:

import re
from operator import methodcaller
from functools import partial

我下面的第一个函数能够适应所使用的正则表达式方法的变化:

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)

它按预期工作:

>>> rule_parser_re_1(**rule_1)
<re.Match object; span=(0, 6), match='s_test'>

现在,假设在定义配置字典时我没有要解析的字符串。

例如,假设它是文件中的特定行,只能在运行时访问。

myfile = """
first line
second line
third line
"""

io_myfile = io.StringIO(myfile)

content = io_myfile.readlines()

我的第二条规则,其中“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,
    }
}

我的理解是我应该能够通过定义一个偏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

这似乎也可以正常工作:

>>> r2 = rule_parser_re_2(**rule_2)
>>> r2(string=content[2])
<re.Match object; span=(0, 6), match='second'>

虽然,我看到上述实现有两个可维护性问题:

  1. 我正在使用该if语句,它迫使我为re我想要支持的每个方法修改函数;
  2. 我需要明确指定参数,而不仅仅是解压“**kwargs”

我的目标/怀疑:

  • 有什么办法可以使上述功能更加动态和可维护吗?
  • functools.partial()operator.methodcaller()对工作的合适的工具?
  • 如果可以,它们可以组合在一起吗?

谢谢!

以上是在Python中创建动态部分可调用对象的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>