在Python中设置函数签名 [英] Set function signature in Python

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

问题描述

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





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


  • 将f2的非关键字参数设置为l中的字符串
  • 将f2的关键字参数设置为d中的键,并将默认值设置为d



即。假设我们有

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

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

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

  def f2(x,y,opt = None): 
#我的代码

特定用例



这只是我特定用例的简化版本。我仅以此为例。



我的实际用例(简化)如下所示。我们有一个通用的初始化函数:

$ p $ def $ generic_init(self,* args,** kwargs):
函数启动一个通用对象
为名字,arg in zip(self .__ init_args __,args):
setattr(self,name,arg)
为名字,默认为self .__ init_kw_args __。items():
如果名字在kwargs中:
setattr(self,name,kwargs [name])
else:
setattr(self,name,default)

我们想在许多类中使用这个函数。特别是,我们希望创建一个函数 init ,它的行为与generic_init类似,但是在创建时间时具有由某些类变量定义的签名:

  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?



请注意:


  • 如果我只是想要改进帮助,我可以设置 doc

  • 我们希望在创建时设置函数签名。
  • 不是创建一个像generic_init这样的函数,而是使用不同的签名,我们可以创建一个新的函数,只需调用generic_init

  • 我们要定义create_initiation_function。我们不想手动指定新功能!



相关


解决方案

对于您的用例,在类/函数中有一个文档字符串应该可以工作 - 这将在help()中显示出来,并且可以通过程序设置(func .__ doc__ =stuff)。

<我看不到任何设置实际签名的方法。如果可行的话,我会认为 functools模块可以做到,但它不会't,至少在py2.5和py2.6中。



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



嗯,如果你不介意真正邪恶,你可以使用compile()/ eval()来完成它。如果您想要的签名由arglist = [foo,bar,baz]指定,并且您的实际函数为f(* args,** kwargs),则您可以管理:

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

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

更改docstring和func_name应该为您提供完整的解决方案。但是,呃,呃...

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

More detail

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

  • 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

ie. Suppose we have

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

A specific use case

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)

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__)

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 writ create_initiation_function?

Please note:

  • 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!

Related

解决方案

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").

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.

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

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):\n    return real_func(%s)\n" % (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)

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

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆