gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 11:29:44 25 4
gpt4 key购买 nike

我在 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”(即 int )替换“string”(即 str )。
rule_2 = {
'kind': 'regex',
'method': 'match',
'args': None,
'kwargs': {
'pattern': "[a-z_]+",
'flags': re.X,
'line_number': 2,
}
}
我的理解是,我应该能够通过定义部分 rule_parser_re 来解决这个问题。功能。
这样的函数应该表现得像用 pattern 调用的原始函数一样和 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'>
虽然,我看到上述实现有两个可维护性问题:
  • 我正在使用那个 if强制我为每个 re 修改函数的语句我想支持的方法;
  • 我需要明确指定参数,而不仅仅是解压 "**kwargs"

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

  • 谢谢!

    最佳答案

    与其尝试部分或方法调用者,为什么不直接调用函数,只使用 kwargs,而是使用配置来驱动大部分 kwargs/args 内容?我为此使用了一个闭包,其中准备好的“记住”配置。
    请注意,我的最终调用并不关心字符串是 re.match 的关键字。我发现你的例子与正则表达式特定的东西有相当多的耦合,其中一些像 re.X如果不进一步操作,则无法存储在 YAML 中。
    同样,partial/methodcaller 调用函数的方式不应该关心值来自文件中的哪个行号,这太耦合了。如果必须,请在配置中添加其他内容,不是 kwargs ,处理运行时参数获取。
    所以我改变了一些东西。我相信,但你可能不同意,在调用解析规则时,调用函数不应该知道参数是如何被调用的。嗯,也就是说,除非你的规则只是风格上的正则表达式,在这种情况下你不需要 kind在配置中。
    这是一个 快速,不完美,草图 的替代方法。详细信息将取决于您想要如何使用它。
    我也赌了 *args处理,尽管如果必须,它可能会以相同的方式进行。

    import importlib

    rule_1 = {
    'kind': 're',
    'method': 'match',
    'args': None,
    "positional_mapper" : ["string"],
    'kwargs': {
    'pattern': "[a-z_]+",
    # I don't know how this would be stored in a YAML
    # 'flags': re.X,
    'string': 's_test.log',
    }
    }

    rule_2 = {
    'kind': 're',
    'method': 'match',
    'args': None,
    "positional_mapper" : ["string"],
    'kwargs': {
    'pattern': "[a-z_]+",
    }
    }


    def prep(config):

    mod = app_urls = importlib.import_module(config["kind"])
    f = getattr(mod, config["method"])

    pre_args = config.get("args") or []
    pre_kwargs = config.get("kwargs") or {}
    positional_mapper = config["positional_mapper"]

    def prepped(*args, **kwargs):

    kwargs2 = pre_kwargs.copy()

    for value, argname in zip(args, positional_mapper):
    kwargs2[argname] = value
    kwargs2.update(**kwargs)

    return f(**kwargs2)

    return prepped


    parsed_rule1 = prep(rule_1)

    print ("#1", parsed_rule1("second line"))
    print ("#2", parsed_rule1())

    parsed_rule2 = prep(rule_2)
    print ("#3", parsed_rule2("second line"))
    print ("#3.5", parsed_rule2(string="second line"))
    print ("#4", parsed_rule2())

    正如预期的那样,调用 #4 chokes,因为它缺少要放入 string 的参数。 .
    #1 <re.Match object; span=(0, 6), match='second'>
    #2 <re.Match object; span=(0, 6), match='s_test'>
    #3 <re.Match object; span=(0, 6), match='second'>
    #3.5 <re.Match object; span=(0, 6), match='second'>
    Traceback (most recent call last):
    File "test_299_dyn.py:57", in <module>
    print ("#4", parsed_rule2())
    File "test_299_dyn.py:44", in prepped
    return f(**kwargs2)
    TypeError: match() missing 1 required positional argument: 'string'

    关于python - 在 Python 中创建动态部分可调用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67860925/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com