装饰器在python中是经常用到的,装饰器顾名思义是装饰的作用,其实就是一个函数把另外一个函数当作参数而已
函数装饰器
无参数装饰器
需要注意的是
- @cost_time # 装饰没有参数的时候不要写成@cost_time(),带括号表示有参数
- 下面装饰器使用等价于cost_time(main)()
import time ''' 无参数 func参数默认放在最外层 ''' def cost_time(func): # 不带参数 def inner(*args,**kwargs): t1 = time.time() data = func(*args,**kwargs) print("cost time:", time.time() - t1) return data return inner @cost_time # 装饰没有参数的时候不要写成@cost_time(),带括号表示有参数 def main(): time.sleep(1) main()
带参数装饰器
需要注意的是
- 带参数带装饰器函数外面需要多包裹一成,原因是参数需要占用一成
- 装饰器作用等价于:cost_time(arg=’1′)(test_arg)()
''' 有参数装饰器 需要多包裹一成,原因是参数需要占用一成 装饰器作用等价于:cost_time(arg='1')(test_arg)() ''' def cost_time(arg): def middle(func): def inner(*args,**kwargs): t1 = time.time() print("arg:",arg) data = func(*args, **kwargs) print("cost time:", time.time() - t1) return data return inner return middle @cost_time(arg="1") def main(): pass main()
wraps在装饰器中的作用
当函数使用了装饰器之后,函数的一些属性会发生变化,比如函数名,函数__doc__,为了避免函数使用装饰器之后发生属性的变更,wraps就派上用场了,它的作用就是消除装饰器带来的副作用。
下面的函数如果不加@wraps(fun),输出的结果可以自己试试。
def cost_time(arg): def middle(func): @wraps(func) def inner(*args,**kwargs): ''' decorate func ''' t1 = time.time() print("arg:",arg) data = func(*args, **kwargs) print("cost time:", time.time() - t1) return data return inner return middle @cost_time(arg="1") def main(): ''' main func ''' pass print(main.__name__,main.__doc__)
输出的结果
使用类__call__的方式实现装饰器
不带参数的类装饰器
# -*- coding: utf-8 -*- # @Time : 2020/7/27 11:29 上午 # @Author : wsppx # @File : c1.py # @Software: PyCharm import time from functools import wraps class CostTime: def __init__(self): pass def __call__(self, func): ''' 类实现了这个方法,相当于把这个类型的对象当作函数来使用。 ''' @wraps(func) def inner(*args, **kwargs): print("use call:") t1 = time.time() data = func(*args, **kwargs) print("cost time:", time.time() - t1) return data return inner @CostTime() def main(): time.sleep(0.5) main() class A(): @CostTime() def say(self): print("hello") def pick(self): print("pick you") a = A() a.say() a.pick()
也可以用最简单的方式
import time class CostTime: def __init__(self,func): print("init class") self.func = func def __call__(self, *args, **kwargs): ''' 类实现了这个方法,相当于把这个类型的对象当作函数来使用。 ''' print("use call:") t1 = time.time() data = self.func(*args, **kwargs) print("cost time:", time.time() - t1) return data @CostTime def main(): time.sleep(0.5) main() print("-"*30) @CostTime class A(): def say(self): print("hello") def pick(self): print("pick you") a = A() a.say() a.pick()
使用类的方式实现装饰器
类装饰器什么时候会用到呢?当你装饰类的时候会用到,当然普通函数也可以,但是如果设计到
class CostTime: def decorate(self,func): @wraps(func) def inner(*args, **kwargs): t1 = time.time() data = func(*args, **kwargs) print("cost time:", time.time() - t1) return data return inner @staticmethod def static_decorate(func): def innert(*args,**kwargs): data = func(*args,**kwargs) return data return innert ct = CostTime() class A(object): @ct.decorate # 实例方法装饰 def say(self): print("hello") @CostTime.static_decorate # 类静态方法装饰 def pick(self): print("pick you") a = A() a.say() a.pick() @ct.decorate # 实例方法装饰普通函数 def main(): time.sleep(0.5) main()
原创文章,作者:站长,如若转载,请注明出处:https://wsppx.cn/631/%e7%bd%91%e7%bb%9c%e5%bc%80%e5%8f%91/%e5%90%8e%e7%ab%af/