本文介绍了在 Python 中设置函数签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个通用函数 f.我想以编程方式创建一个函数 f2,其行为与 f 相同,但具有自定义签名.

Suppose I have a generic function f. I want to programmatically create a function f2 that behaves the same as f, but has a customized signature.

更多细节

给定一个列表 l 和字典 d 我希望能够:

Given a list l and and dictionary d I want to be able to:

  • f2的非关键字参数设置为l
  • 中的字符串
  • 设置f2的关键字参数为d中的key,默认值为d
  • Set the non-keyword arguments of f2 to the strings in l
  • Set the keyword arguments of f2 to the keys in d and the default values to the values of d

即.假设我们有

l = ["x", "y"]
d = {"opt": None}

def f(*args, **kwargs):
    # My code

然后我想要一个带有签名的函数:

Then I would want a function with signature:

def f2(x, y, opt=None):
    # My code

特定用例

这只是我的特定用例的简化版本.我只是举个例子.

This is just a simplified version of my specific use case. I am giving this as an example only.

我的实际用例(简化)如下.我们有一个通用的启动函数:

My actual use case (simplified) is as follows. We have a generic initiation function:

def generic_init(self, *args, **kwargs):
    """Function to initiate a generic object"""
    for name, arg in zip(self.__init_args__, args):
        setattr(self, name, arg)
    for name, default in self.__init_kw_args__.items():
        if name in kwargs:
            setattr(self, name, kwargs[name])
        else:
            setattr(self, name, default)

我们想在许多类中使用这个函数.特别是,我们想要创建一个函数 __init__,其行为类似于 generic_init,但具有在创建时由某些类变量定义的签名:

We want to use this function in a number of classes. In particular, we want to create a function __init__ that behaves like generic_init, but has the signature defined by some class variables at creation time:

class my_class:
    __init_args__ = ["x", "y"]
    __kw_init_args__ = {"my_opt": None}

__init__ = create_initiation_function(my_class, generic_init)
setattr(myclass, "__init__", __init__)

我们希望 create_initiation_function 使用 __init_args____kw_init_args__ 定义的签名创建一个新函数.是否可以编写create_initiation_function?

We want create_initiation_function to create a new function with the signature defined using __init_args__ and __kw_init_args__. Is it possible to write create_initiation_function?

请注意:

  • 如果我只是想改进帮助,我可以设置__doc__.
  • 我们想在创建时设置函数签名.之后,就不需要更改了.
  • 不是创建像 generic_init 这样的函数,而是使用不同的签名,我们可以创建一个具有所需签名的新函数,只需调用 generic_init
  • 我们要定义create_initiation_function.我们不想手动指定新函数!
  • If I just wanted to improve the help, I could set __doc__.
  • We want to set the function signature on creation. After that, it doesn't need to be changed.
  • Instead of creating a function like generic_init, but with a different signature we could create a new function with the desired signature that just calls generic_init
  • We want to define create_initiation_function. We don't want to manually specify the new function!

相关

  • Preserving signatures of decorated functions: This is how to preserve a signature when decorating a function. We need to be able to set the signature to an arbitrary value

推荐答案

对于你的用例,在类/函数中有一个文档字符串应该可以工作——它会出现在 help() 中,可以,并且可以以编程方式设置 (func.__doc__ = "东西").

For your usecase, having a docstring in the class/function should work -- that will show up in help() okay, and can be set programmatically (func.__doc__ = "stuff").

我看不到任何设置实际签名的方法.如果可行,我本以为 functools 模块 会完成它,但它没有't,至少在 py2.5 和 py2.6 中是这样.

I can't see any way of setting the actual signature. I would have thought the functools module would have done it if it was doable, but it doesn't, at least in py2.5 and py2.6.

如果输入错误,您也可以引发 TypeError 异常.

You can also raise a TypeError exception if you get bad input.

嗯,如果你不介意真正的卑鄙,你可以使用 compile()/eval() 来做到这一点.如果你想要的签名是 arglist=["foo","bar","baz"] 指定的,而你的实际函数是 f(*args, **kwargs),你可以管理:

Hmm, if you don't mind being truly vile, you can use compile()/eval() to do it. If your desired signature is specified by arglist=["foo","bar","baz"], and your actual function is f(*args, **kwargs), you can manage:

argstr = ", ".join(arglist)
fakefunc = "def func(%s):
    return real_func(%s)
" % (argstr, argstr)
fakefunc_code = compile(fakefunc, "fakesource", "exec")
fakeglobals = {}
eval(fakefunc_code, {"real_func": f}, fakeglobals)
f_with_good_sig = fakeglobals["func"]

help(f)               # f(*args, **kwargs)
help(f_with_good_sig) # func(foo, bar, baz)

更改文档字符串和 func_name 应该可以为您提供完整的解决方案.但是,呃,呃...

Changing the docstring and func_name should get you a complete solution. But, uh, eww...

这篇关于在 Python 中设置函数签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 12:25