【问题标题】:Creating functools.partial *args & *kwargs from parsed strings从解析的字符串创建 functools.partial *args & *kwargs
【发布时间】:2010-10-13 00:35:52
【问题描述】:

我正在传递我想使用 functools.partial 将其转换为方法调用的字符串列表:

[ 'object1.method1(arg1, arg2, 4, key=value)', 'object2.method2(6, arg1)' ...]

使用正则表达式为 functools.partial 生成必要的 'func' 参数很容易,但是我很容易将括号中的字符串转换为有效的 *args 和 **kwargs 以传递给functools.partial.

保证每个列表项都是有效的 Python。我只是无法想出一种快速、简单的方法来将诸如 'arg1, arg2, 4, key=value' 之类的字符串转换为 functools.partial 可以使用的东西。我错过了什么?

更新:

我的道歉。我确实忘记了重要信息。 args 不是此过程范围内的有效标识符,因此“eval”不起作用。但是,它们在使用结果部分对象的范围内是正确的,因此可以将它们“复制”为文字。 我当前的过程返回一个字符串 'arg1, arg2, 4, this=that'。如果直接传递给 functools.partial,functools.partial 会将其“包装”为单个字符串参数。

嗯……我描述得越多,我就越意识到除非这些标识符在此范围内有效,否则无法做到这一点……

【问题讨论】:

  • 由于这些是部分的,因此是“arg1”、“arg2”等占位符,用于稍后提供的值,而不是可能会使用的文字“4”和“6”在创建部分?用于部分命名参数的占位符与文字语法是什么? “object1”是占位符吗?也许如果你展示了之前和之后的案例 - “对于字符串'blah',我会创建这个部分”。
  • object1、arg1、arg2、object2等在哪里定义?即范围。它们是在 locals() 或 globals() 中定义的,还是在您创建 functools.partial 函数的地方定义的? eval 甚至是一个可行的选择吗?

标签: python partial


【解决方案1】:

我正在写另一个答案,因为如果我更改旧答案,cmets 根本不会反映内容。相反,如果事实证明这是一个更好的答案,我将撤回另一个。以下应该可以工作。

操作理论:

  1. 获取您的功能
  2. 为参数剖析字符串
  3. 将每个参数与其自己的 eval 放在一个部分中
  4. 将包装器、函数和部分参数放在一个部分中
  5. 在需要的范围内执行

以下代码集中在 2.-4。假设进口。当然还有一个额外的名称冲突问题,因为作用域中的附加代码


def wrapper(func_, *args, **kw):
    new_args = []
    new_kw = {}
    for arg in args:
        if type(arg)==functools.partial:
            arg = arg()
        new_args.append(arg)
    for key in kw:
        value = kw[key]
        if type(value)==functools.partial:
            value = value()
        new_kw[key]=value
     return func_(*new_args, **new_kw)

orig_str = 'object1.method1(arg1, arg2, 4, key=value)'
argstr = re.search('.+\((.+)\)', orig_str).group(1)
args = []
kw = {}
for x in argstr.split(','):
    if '=' in x:
        key, value = x.strip().split('=')
    else:
        value = x.strip()
        key = None            
    value = functools.partial(eval, value)
    if key:
        kw[key]=value
    else:
        args.append(value)

what_you_want = functools.partial(wrapper, func, *args, **kw)

【讨论】:

  • 我喜欢你的概念,在 args 周围放置一个包装器,在执行时评估它们——假设它们将在那里定义。我会将此标记为答案,但我建议未来的读者将上述内容视为伪代码。谢谢,克尼蒂。好主意!
【解决方案2】:

使用 eval 函数很简单,并用自定义函数名称替换函数名称,无需正则表达式。

def get_args_and_kwargs(*args, **kwargs):
    return args, kwargs

def convert_str_to_args_and_kwargs(s):
    return eval(s.replace(s[:s.find('(')], 'get_args_and_kwargs'))

for s in your_list:
    args, kwargs = convert_str_to_args_and_kwargs(s)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 2013-09-25
    • 2021-07-26
    • 2021-03-20
    • 1970-01-01
    • 2014-06-18
    • 2016-01-19
    相关资源
    最近更新 更多