问题描述
假设我有一个通用函数 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 inl
- Set the keyword arguments of
f2
to the keys ind
and the default values to the values ofd
即.假设我们有
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 callsgeneric_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 中设置函数签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!