参考:
https://www.runoob.com/w3cnote/python-func-decorators.html
https://www.jb51.net/article/240440.htm
用途:定义一个函数,来修饰之前老的代码,以便在不修改原代码的情况下增加新功能
关键原理:把函数作为参数,函数后面不加()就可以随意传递,加了()函数就会执行
一. 第一个装饰器例子
1.基本功能实现
def deco(func):
def inner():
print("something before hi")
func()
print("something after hi")
return inner
def hi():
print("hi")
hi=deco(hi)
hi()
这正是 python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为
2.现在用符号@来修改上面代码
def deco(func):
def inner():
print("something before hi")
func()
print("something after hi")
return inner
@deco
def hi():
print("hi")
hi()
print(hi.__name__) //输出为inner
@deco其实就相当于hi=deco(hi)
不过现在最后一个行输出为inner, 我们想把它输出为hi,应该怎么做呢?
幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps
3. functools.wraps改写
from functools import wraps
def deco(func):
@wraps(func)
def inner():
print("something before hi")
func()
print("something after hi")
return inner
@deco
def hi():
print("hi")
hi()
print(hi.__name__) //输出为hi
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
二. 带参数的装饰器
from functools import wraps
import time
def delay_deco(delay=0):
def deco(func):
@wraps(func)
def inner():
print("something before hi")
time1 = time.time()
time.sleep(delay)
time2 = time.time()
func()
print("something after hi")
print("耗时:{:.8f}".format(time2-time1))
return inner
return deco
@delay_deco(2.0)
def hi():
print("hi")
hi()
print(hi.__name__)
其实就是在原先的基础上,再加一层嵌套。上面代码实现延迟2秒执行,参数就是延迟的时间
三. 类装饰器
装饰器本身既可以是函数也可以是类,装饰的对象同样可以是函数也可以是类。
1. 最简单的例子
class Deco:
def __init__(self, func):
self._func = func
def __call__(self, *args, **kwargs): #定义__call__函数,让类实例成为可调用对象
print("类装饰器")
return self._func(*args, **kwargs)
@Deco
def test():
print("被装饰函数")
test()
例子2:根据例子1,稍微复杂点,被装饰的函数中添加参数
import time
class Deco:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start = time.time()
ret = self.func(*args, **kwargs)
print(f'Time: {time.time()-start}')
return ret
@Deco
def add(a,b):
time.sleep(1)
return a+b
print(add(3,4))
这个装饰器,相当于把一个装饰器变成了一个Deco类的对象,然后add被传入进了init中,保存为self.func
在后面调用add(3,4)的时候,实际上相当于调用了call这个函数,做了一个对象的调用,后面参数3和4就被传入到了call里面,然后依顺序运行了代码。
例子3:带参数的类装饰器
import time
class Deco:
def __init__(self, prefix):
self.prefix = prefix
def __call__(self, func):
def inner(*args, **kwargs):
start = time.time()
ret = func(*args, **kwargs)
print(f'{self.prefix}: {time.time()-start}')
return ret
return inner
@Deco(prefix='current_time')
def add(a,b):
time.sleep(1)
return a+b
print(add(3,4))
我们把参数写入init函数中,相当于先实例化了一个Deco对象,call函数内做一个嵌套,类似于函数装饰器
标签:__,python,hi,func,time,print,装饰,def From: https://www.cnblogs.com/regit/p/16802360.html