如何定义带参数的装饰器PYTHON

#如何为被装饰的函数保存元数据
from functools import update_wrapper,wraps
def mydecorator(func):
    def wrapper(*args,**kargs):
        print('in wrapper')
        func(*arg,**kargs)
    update_wrapper(wrapper,func,('__name__','__doc__'),('__dict__',))
    return wrapper
@mydecorator
def example():
    print('in example')
#如何定义带参数的装饰器
#实现一个装饰器,它用来检查被装饰函数的参数类型,
#装饰器可以通过参数指明函数参数的类型,调用时如果检测出类型不匹配则抛出异常
'''
@typeassert(str,int,int)
def f(a,b,c):
....
@typeassert(y=list)
def g(x,y):
....
'''
#解决方案:提取函数签名:inspect.signature()
#带参数的装饰器,也就是根据参数定制化一个装饰器,可以看成生产装饰器的工厂,
#每次调用typeassert,返回一个特定的装饰器,然后用它去装饰其他函数
from inspect import signature
def typeassert(*ty_args,**ty_kargs):
    def decorator(func):
        #获取函数参数与类型之间的关系  建立字典
        #func->a,b
        #d={'a':int,'b':str}
        sig=signature(func)
        btypes=sig.bind_partial(*ty_args,**ty_kargs).arguments
        def wrapper(*args,**kargs):
            # arg in d ,istance(arg,d[arg])
            for name,obj in sig.bind(*args,**kargs).arguments.items():
                if name in btypes:
                    if not isinstance(obj,btypes[name]):
                        raise TypeError('"%s" must be "%s"' % (name,btypes[name]))
            return func(*args,**kargs)
        return wrapper
    return decorator
@typeassert(int,str,list)
def f(a,b,c):
    print(a,b,c)
    
f(1,'abc',[1,2,3])

#获取函数的签名
from inspect import signature
def f(a,b,c):
sig=signature(f)
a=sig.parameters['a']
'''
a.name
a.kind
a.default
'''
bargs=sig.bind(str,int,int)
'''
bargs.arguments包含了需要建立的字典
bargs.arguments['a']
'''
sig.bind_partial(str)

猜你喜欢

转载自blog.csdn.net/weixin_38858860/article/details/89108697