当前位置: 首页 > 后端技术 > Python

python3-装饰器基础使用

时间:2023-03-26 01:33:49 Python

知识点简单装饰器装饰器带参数装饰器类装饰器装饰器嵌套@functools.wrap装饰器使用简单装饰器使用基础defmy_decorator(func):defwrapper():print('wrapperofdecorator')func()returnwrapper()deftest():print('testdone.')test=my_decorator(test)testoutput:decoratortestdone的包装器。这段代码中,变量test指向了内部函数wrapper(),内部函数wrapper()会调用原来的函数test(),所以最后调用test()时,会打印'wrapperofdecorator'和然后输出“测试完成”。这里的函数my_decorator()是一个装饰器,把真正需要执行的函数test()包装起来,改变了它的行为,但是原来的函数test()保持不变。上述代码在Python中的更简单和更优雅的表示:defmy_decorator(func):defwrapper():print('wrapperofdecorator')func()returnwrapper()@my_decoratordeftest():print('testdone.')test中的@被称为句法糖。@my_decorator相当于前面的test=my_decorator(test)语句。如果程序中还有其他函数需要类似的装饰,只需添加@decorator即可提高函数的性能。重用和程序可读性带参数的装饰器defargs_decorator(func):defwrapper(*args,**kwargs):print('wrapperofdecorator')func(*args,**kwargs)returnwrapper@args_decoratordefidentity(name,message):print('identitydone.')print(name,message)identity('changhao','hello')输出:decoratoridentitydone.changhaohello的包装器通常,args和*kwargs,作为wrapper()内部的参数装饰器的功能。表示它接受任何数量和类型的参数。自定义参数的装饰器定义了一个参数,表示装饰器内部函数执行的次数。可以这样写:defrepeat(num):defmy_decorator(func):defwrapper(*args,**kwargs):foriinrange(num):func(*args,**kwargs)returnwrapperreturnmy_decorator@repeat(3)defshowname(message):print(message)showname('changhao')输出:changhaochanghaochanghao类装饰器类也可以作为装饰器,类装饰器主要依靠函数__call__函数__call__()将每次调用示例时执行一次。classCount:def__init__(self,func):self.func=funcself.num_calls=0def__call__(self,*args,**kwargs):self.num_calls+=1print('调用次数为:{}'.format(self.num_calls))returnself.func(*args,**kwargs)@Countdefexample():print('exampledone.')example()example()output:numofcallsis:1例子done.numofcalls是:2exampledone。这里定义了类Count,初始化时传入了原函数func(),__call__()函数表示变量num_calls加1,然后打印,调用原函数。所以当我们第一次调用函数example()时,num_calls的值是1,第一次调用时值就变成了2。装饰器的嵌套importfunctoolsdefmy_decorator1(func):@functools.wraps(func)defwrapper(*args,**kwargs):print('executedecorator1')func(*args,**kwargs)returnwrapperdefmy_decorator2(func):@functools.wraps(func)defwrapper(*args,**kwargs):print('执行decorator2')func(*args,**kwargs)returnwrapper@my_decorator1@my_decorator2deftest2(message):print(message)test2('changhao')output:executedecorator1executedecorator2changhao@functools.wrap装饰器使用importfunctoolsdefmy_decorator(func):@functools.wraps(func)defwrapper(*args,**kwargs):print('wrapperofdecorator')func(*args,**kwargs)returnwrapper@my_decoratordeftest3(message):print(message)test3.__name__输出的test3通常使用内置的装饰器@functools.wrap,它会保留原函数(即把原函数的元信息复制到对应的装饰器中)装饰器使用实例认证importfunctoolsdefauthenticate(func):@functools.wraps(func)defwrapper(*args,**kwargs):request=args[0]如果check_user_logged_in(request):returnfunc(*args,**kwargs)else:raiseException('Authenticationfailed')returnwrapper@authenticatedefpost_comment(request):pass这段代码中定义了装饰器authenticate;post_comment()函数,表示发表用户对文章的评论。每次调用该函数前,都会检查用户是否登录,如果用户登录,则允许该操作;如果未登录,则不允许。记录导入时间importfunctoolsdeflog_execution_time(func):@functools.wraps(func)defwrapper(*args,**kwargs):start=time.perf_counter()res=func(*args,**kwargs)end=time.perf_counter()print('{}take{}ms'.format(func.__name__,(end-start)*1000))returnwrapper@log_execution_timedefcalculate_similarity(times):pass这里装饰器log_execution_time记录了一个函数的运行时间,并返回其执行结果。如果你想计算任何函数的执行时间,在这个函数上面加上@log_execution_time。总结一下,所谓装饰器,其实就是通过装饰器函数对原函数的一些功能进行修改,使得原函数不需要修改。