Python: 拷貝函數簽名

使用場景有不少,好比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

用起來大概是這一個樣子:函數

  • 首先,函數簽名確定是變了,在IPython下立馬能看到函數提示變化:

image

  • 其次,是函數調用參數符合簽名時,正常使用:

image

  • 最後,是函數調用參數不符合簽名時,會報詳細錯誤:

image

目前實現的signature可以控制是否拷貝簽名函數的函數名,對於doc也能夠實現相似的可控制的參數。rest

相關文章
相關標籤/搜索