如何使用同一个装饰器同时修饰函数和类方法?
如何使用同一个装饰器同时修饰函数和类方法?
哎,这个问题我之前也踩过坑!完全不用写两个名字不一样的装饰器,咱们只要把装饰器改得更灵活一点,就能让它同时适配普通函数和类方法啦~
先说说你原来的代码为啥会出问题:普通函数sumup接收两个参数a和b,但类里的sumup方法第一个参数是self(也就是类实例本身),原来的装饰器里的decorator函数固定只接收a和b两个参数。当你调用cls.sumup(4,8)时,Python实际会把cls(实例)、4、8这三个参数传进去,可装饰器的decorator只接两个参数,自然就会报参数不匹配的错误。
那怎么改呢?其实很简单,让装饰器的内层函数支持可变参数就行,用*args来接收所有位置参数,不管是函数的两个参数,还是方法的三个参数,都能一股脑传进去给原函数。
修改后的装饰器代码是这样的:
from functools import wraps def nice(f): @wraps(f) def decorator(*args, **kwargs): # 把所有接收到的参数原封不动传给原函数 result = f(*args, **kwargs) return 'result is: %s' % str(result) return decorator
然后你原来的测试代码完全不用改,直接用这个装饰器同时修饰函数和类方法:
@nice def sumup(a, b): return a + b class Test: def __init__(self): pass @nice def sumup(self, a, b): return a + b print(sumup(2, 6)) # 输出:result is: 8 cls = Test() print(cls.sumup(4, 8)) # 输出:result is: 12
你看,这样不管是普通函数还是类方法,这个装饰器都能完美胜任!
如果你的原函数还需要接收关键字参数,那上面代码里的**kwargs已经帮你处理好了,连关键字参数也能正确传递,通用性更强。
当然,如果你想更严谨地处理,也可以通过检查原函数的参数签名来区分是函数还是方法,但用*args+**kwargs是最简洁通用的方案,比写两个不同名字的装饰器优雅太多了~
备注:内容来源于stack exchange,提问作者IzaeDA
相关产品推荐
相关产品推荐

