Python 装饰器
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
1 import time 2 3 def show_time(func): 4 def wrapper(): 5 start_time=time.time() 6 func() 7 end_time=time.time() 8 print('spend %s'%(end_time-start_time)) 9 10 return wrapper 11 12 13 def foo(): 14 print('hello foo') 15 time.sleep(3) 16 17 foo=show_time(foo) 18 foo()
函数show_time就是装饰器,它把真正的业务方法func包裹在函数里面,看起来像foo被上下时间函数装饰了。在这个例子中,函数进入和退出时 ,被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。
@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作
1 import time 2 3 def show_time(func): 4 def wrapper(): 5 start_time=time.time() 6 func() 7 end_time=time.time() 8 print('spend %s'%(end_time-start_time)) 9 10 return wrapper 11 12 @show_time #foo=show_time(foo) 13 def foo(): 14 print('hello foo') 15 time.sleep(3) 16 17 18 @show_time #bar=show_time(bar) 19 def bar(): 20 print('in the bar') 21 time.sleep(2) 22 23 foo() 24 print('***********') 25 bar()
装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。
带参数的被修饰函数
1 import time 2 3 def show_time(func): 4 5 def wrapper(a,b): 6 start_time=time.time() 7 func(a,b) 8 end_time=time.time() 9 print('spend %s'%(end_time-start_time)) 10 11 return wrapper 12 13 @show_time #add=show_time(add) 14 def add(a,b): 15 16 time.sleep(1) 17 print(a+b) 18 19 add(2,4)
装饰器带参数
import time def time_logger(flag=0): def show_time(func): def wrapper(*args,**kwargs): start_time=time.time() func(*args,**kwargs) end_time=time.time() print('spend %s'%(end_time-start_time)) if flag: print('将这个操作的时间记录到日志中') return wrapper return show_time @time_logger(3) # add = time_loger(3)(add) def add(*args,**kwargs): time.sleep(1) sum=0 for i in args: sum+=i print(sum) add(2,7,5)
-------------------------------------------------------
补全
import time def cal_time(func): def inter(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s time: %s" % (func.__name__, t2 - t1)) return result return inter @cal_time def add(x, y): return x + y
当使用一个装饰器时,打印函数名会出现问题
print(add.__name__) ##输出 inter
使用标准库里的
functools.wraps,可以基本解决这个问题
看的别人写的文章说是拿不到数字签名等信息,但是在Python3.5里面可以拿到
可以使用wrapt包来进行修正
Wrapt
需要安装
pip install wrapt
wrapt是一个功能非常完善的包,用于实现各种你想到或者你没想到的装饰器。使用wrapt实现的装饰器你不需要担心之前inspect中遇到的所有问题,因为它都帮你处理了,甚至
inspect.getsource(func)也准确无误。
import wrapt @wrapt.decorator def cal_time(func, instance, args, kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s time: %s" % (func.__name__, t2 - t1)) return result @cal_time def add(x, y): return x + y
使用wrapt你只需要定义一个装饰器函数,但是函数签名是固定的,必须是
(wrapped, instance, args, kwargs),注意第二个参数
instance是必须的,就算你不用它。当装饰器装饰在不同位置时它将得到不同的值,比如装饰在类实例方法时你可以拿到这个类实例。根据
instance的值你能够更加灵活的调整你的装饰器。另外,
args和
kwargs也是固定的,注意前面没有星号。在装饰器内部调用原函数时才带星号。
如果你需要使用wrapt写一个带参数的装饰器,可以这样写。
def logging(level): @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): print("[{}]: enter {}()".format(level, wrapped.__name__)) return wrapped(*args, **kwargs) return wrapper @logging(level="INFO") def do(work): pass
类装饰器及更多内容
详解Python的装饰器
Python装饰器的另类用法
转载于:https://www.cnblogs.com/bw13/p/5850367.html
- 点赞
- 收藏
- 分享
- 文章举报
- Python中装饰器的理解
- Python 之 装饰器
- python 装饰器 code
- Python19_装饰器【重点】
- python-实现属性可修改的函数装饰器-28
- python高级之装饰器
- python 装饰器
- python 函数装饰器学习
- python中关于装饰器的理解
- [python]装饰器及其使用
- Python中的装饰器详解
- python 装饰器
- python--多个装饰器
- Python 装饰器
- python 装饰器
- python 装饰器
- 没看完这11 条,别说你精通 Python 装饰器
- 自学Python4.5-装饰器举例
- Python之杂学(闭包、运算效率、装饰器、生成器、斐波那锲、迭代器)
- Python帮你微信头像任意添加装饰别再@微信官方了