使用场景有不少,好比C API在Python下不少都变成了(*args, **kwargs)的参数,这时候可能须要为其添加一个更严格签名来约束参数。html
查了许多资料,能有效的拷贝函数签名貌似只能经过动态建立具备新签名的包装函数。使用这一技术的典型范例就是decorator库:https://pypi.python.org/pypi/decoratorpython
下面就根据decorator来实现一个拷贝函数签名的decorator:app
from decorator import FunctionMaker, decorator from contextlib import contextmanager @contextmanager def rename_scope(obj, new_name): """ A rename scope to rename obj's __name__, restore __name__when exit. """ old_name = obj.__name__ obj.__name__ = new_name yield obj.__name__ = old_name def newcaller(caller, sig_func): """ Generate a new caller using sig_func signatures, doc and name, etc. """ evaldict = sig_func.func_globals.copy() evaldict['_call_'] = caller return FunctionMaker.create( sig_func, "return _call_(%(shortsignature)s)", evaldict, signature=sig_func) def signature(sig_func, copy_name=False): """ A decorator to update function signature, doc by sig_func. If copy_name, the return function use sig_func name else function keep its name. """ def sig_wrapper(caller): with rename_scope(sig_func, sig_func.__name__ if copy_name else caller.__name__): return newcaller(caller, sig_func) return sig_wrapper
用起来大概是这一个样子:函数
目前实现的signature可以控制是否拷贝签名函数的函数名,对于doc也能够实现相似的可控制的参数。rest