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

发布于 2024-09-27 13:01:18 字数 654 浏览 2 评论 0原文

我正在传递一些字符串列表,我想使用 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 将其“包装”为单个字符串参数。

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

I am being passed lists of strings that I would like to convert to method calls using functools.partial:

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

It's easy to use a regexp to generate the necessary 'func' argument to functools.partial, but I'm having a devil of a time easily converting the string within the parens into valid *args and **kwargs to pass to functools.partial.

Every list item is guaranteed to be valid Python. I'm just unable to come up with a quick, easy way to convert strings such as 'arg1, arg2, 4, key=value' into somehthing functools.partial can use. What am I missing?

Update:

My appologies. I did forget vital information. The args are not valid identifiers within the scope of this procedure, hence 'eval' doesn't work. They are, however, correct in the scope in which the resulting partial objects will be used, so they can be "copied" as literals.
My current procedure returns a string 'arg1, arg2, 4, this=that'. If passed directly to functools.partial, functools.partial "wraps" it as a single string argument.

Hmmm.. the more I describe this, the more I realize that there's no way to do this unless these identifiers are valid within this scope...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清音悠歌 2024-10-04 13:01:18

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

操作原理:

  1. 获取参数的 func
  2. 剖析字符串
  3. 将每个参数及其自己的 eval 放在一个部分中
  4. 放置一个包装器,func 和部分中的部分参数在
  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)

I'm writing another answer, because if I change the old one, the comments won't reflect the the content at all. Instead, if this turns out to be a better answer, I will withdraw the other. The following should work.

Theory of Operation:

  1. Obtain your func
  2. dissect string for arguments
  3. put every argument together with its own eval in a partial
  4. put a wrapper, func and the partial'd arguments in a partial
  5. execute in the scope needed

The following code concentrates on 2.-4. Imports are assumed. Of course there is an additional problem of names colliding, because of the additional code in the scope


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)
执着的年纪 2024-10-04 13:01:18

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

Easy enough using the eval function and replace the function name with a custom one, no regex necessary.

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文