我正在使用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会将其“包装”为单个字符串参数。
嗯...我描述的越多,我越发现除非这些标识符在此范围内有效,否则无法做到这一点......
答案 0 :(得分:2)
我正在写另一个答案,因为如果我更改旧答案,评论将根本不会反映内容。相反,如果这是一个更好的答案,我会撤回另一个。以下应该有效。
操作理论:
以下代码集中在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)