创建functools.partial * args& *来自解析字符串的kwargs

时间:2010-10-13 00:35:52

标签: python partial

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

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

使用正则表达式为functools.partial生成必要的'func'参数很容易,但是我有一个时间的魔鬼很容易将parens中的字符串转换为有效的* args和** kwargs传递给functools.partial。

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

更新

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

嗯...我描述的越多,我越发现除非这些标识符在此范围内有效,否则无法做到这一点......

2 个答案:

答案 0 :(得分:2)

我正在写另一个答案,因为如果我更改旧答案,评论将根本不会反映内容。相反,如果这是一个更好的答案,我会撤回另一个。以下应该有效。

操作理论:

  1. 获取你的功能
  2. 剖析参数字符串
  3. 将每个参数与其自己的eval一起放入部分
  4. 将一个包装器,func和partial'd参数放在部分
  5. 在所需范围内执行
  6. 以下代码集中在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)
    

答案 1 :(得分:0)

使用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)