python 装饰器的基本使用
知识点
- 简单的装饰器
- 带有参数的装饰器
- 带有自定义参数的装饰器
- 类装饰器
- 装饰器嵌套
- @functools.wrap装饰器使用
基础使用
简单的装饰器
defmy_decorator(func):
defwrapper():
print('wrapperofdecorator')
func()
returnwrapper()
deftest():
print('testdone.')
test=my_decorator(test)
test
输出:
wrapperofdecorator
testdone.
这段代码中,变量test指向了内部函数wrapper(),而内部函数wrapper()中又会调用原函数test(),因此最后调用test()时,就会打印'wrapperofdecorator'然后输出'testdone.'
这里的函数my_decorator()就是一个装饰器,它把真正需要执行的函数test()包裹在其中,并且改变了它的行为,但是原函数test()不变。
上述代码在Python中更简单、更优雅的表示:
defmy_decorator(func):
defwrapper():
print('wrapperofdecorator')
func()
returnwrapper()
@my_decorator
deftest():
print('testdone.')
test
这里的@,我们称为语法糖,@my_decorator就相当于前面的test=my_decorator(test)语句
如果程序中又其他函数需要类似装饰,只需要加上@decorator就可以,提高函数的重复利用和程序可读性
带有参数的装饰器
defargs_decorator(func):
defwrapper(*args,**kwargs):
print('wrapperofdecorator')
func(*args,**kwargs)
returnwrapper
@args_decorator
defidentity(name,message):
print('identitydone.')
print(name,message)
identity('changhao','hello')
输出:
wrapperofdecorator
identitydone.
changhaohello
通常情况下,会把args和*kwargs,作为装饰器内部函数wrapper()的参数。表示接受任意数量和类型的参数
带有自定义参数的装饰器
定义一个参数,表示装饰器内部函数被执行的次数,可以写成这个形式:
defrepeat(num):
defmy_decorator(func):
defwrapper(*args,**kwargs):
foriinrange(num):
func(*args,**kwargs)
returnwrapper
returnmy_decorator
@repeat(3)
defshowname(message):
print(message)
showname('changhao')
输出:
changhao
changhao
changhao
类装饰器
类也可以作装饰器,类装饰器主要依赖于函数__call__每当调用一个示例时,函数__call__()就会被执行一次。
classCount:
def__init__(self,func):
self.func=func
self.num_calls=0
def__call__(self,*args,**kwargs):
self.num_calls+=1
print('numofcallsis:{}'.format(self.num_calls))
returnself.func(*args,**kwargs)
@Count
defexample():
print('exampledone.')
example()
example()
输出:
numofcallsis:1
exampledone.
numofcallsis:2
exampledone.
这里定义了类Count,初始化时传入原函数func(),而__call__()函数表示让变量num_calls自增1,然后打印,并且调用原函数。因此我们第一次调用函数example()时,num_calls的值是1,而第一次调用时,值变成了2。
装饰器的嵌套
importfunctools
defmy_decorator1(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
print('executedecorator1')
func(*args,**kwargs)
returnwrapper
defmy_decorator2(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
print('executedecorator2')
func(*args,**kwargs)
returnwrapper
@my_decorator1
@my_decorator2
deftest2(message):
print(message)
test2('changhao')
输出:
executedecorator1
executedecorator2
changhao
类装饰器
类也可以作装饰器,类装饰器主要依赖于函数__call__每当调用一个示例时,函数__call__()就会被执行一次。
classCount:
def__init__(self,func):
self.func=func
self.num_calls=0
def__call__(self,*args,**kwargs):
self.num_calls+=1
print('numofcallsis:{}'.format(self.num_calls))
returnself.func(*args,**kwargs)
@Count
defexample():
print('exampledone.')
example()
example()
输出:
numofcallsis:1
exampledone.
numofcallsis:2
exampledone.
这里定义了类Count,初始化时传入原函数func(),而__call__()函数表示让变量num_calls自增1,然后打印,并且调用原函数。因此我们第一次调用函数example()时,num_calls的值是1,而第一次调用时,值变成了2。
装饰器的嵌套
importfunctools
defmy_decorator1(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
print('executedecorator1')
func(*args,**kwargs)
returnwrapper
defmy_decorator2(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
print('executedecorator2')
func(*args,**kwargs)
returnwrapper
@my_decorator1
@my_decorator2
deftest2(message):
print(message)
test2('changhao')
输出:
executedecorator1
executedecorator2
changhao
@functools.wrap装饰器使用
importfunctools
defmy_decorator(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
print('wrapperofdecorator')
func(*args,**kwargs)
returnwrapper
@my_decorator
deftest3(message):
print(message)
test3.__name__
输出
test3
通常使用内置的装饰器@functools.wrap,他会保留原函数的元信息(也就是将原函数的元信息,拷贝到对应的装饰器里)
装饰器用法实例
身份认证
importfunctools
defauthenticate(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
request=args[0]
ifcheck_user_logged_in(request):
returnfunc(*args,**kwargs)
else:
raiseException('Authenticationfailed')
returnwrapper
@authenticate
defpost_comment(request):
pass
这段代码中,定义了装饰器authenticate;而函数post_comment(),则表示发表用户对某篇文章的评论。每次调用这个函数前,都会检查用户是否处于登录状态,如果是登录状态,则允许这项操作;如果没有登录,则不允许。
日志记录
importtime
importfunctools
deflog_execution_time(func):
@functools.wraps(func)
defwrapper(*args,**kwargs):
start=time.perf_counter()
res=func(*args,**kwargs)
end=time.perf_counter()
print('{}took{}ms'.format(func.__name__,(end-start)*1000))
returnwrapper
@log_execution_time
defcalculate_similarity(times):
pass
这里装饰器log_execution_time记录某个函数的运行时间,并返回其执行结果。如果你想计算任何函数的执行时间,在这个函数上方加上@log_execution_time即可。
总结
所谓装饰器,其实就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改。
以上就是python装饰器的基本使用的详细内容,更多关于python装饰器的资料请关注毛票票其它相关文章!