Python进阶(四):浅析装饰器(decorator)@

xiaoxiao2021-02-28  21

之前在看代码的时候看见有些代码会在函数前面用一个@+函数名修饰,开始有点困惑的。遂查找各种资料,才知道这是python的一种语法糖。虽然理解起来有点困难,可是理解过后就会佩服python的简洁性。

装饰器@

一.介绍

函数就是我们的衣服,单个函数就比如一件短袖衬衫。编程就是不断的调用不同的函数,就比我们身上穿不同的衣服。当天气变凉的时候我们就必须加外套了,相同的我们需要对某个函数进行某种操作(并且并不想改变这个函数的内部结构)的时候,装饰器就派上了用场。比如我们想知道一个函数完整的执行时间,那么我们可以编写另一个函数B,然后将函数A传递进去,在B的内部计算函数A的执行时间。编写函数B的好处就是下次还要用到的使用就可以直接调用了。但是如果我们在写函数A的时候就想实现计算这个函数A的执行时间(就是每次调用的时候都会计算执行时间),那有什么办法呢?这是@装饰器就起作用了,而且可以很简洁的表示出来

def B(): pass @B def A(): pass ''' 上面的代码相当于 A=B(A) '''

二.通过代码来理解

1.函数的调用

函数在python中是可以作为变量,或者说作为实参传入一个函数的:

def func1(func): print("Start func1") func() print("End func1") def func2(): print("Start func2") print("End func2") func1(func2)

结果:

2.函数的嵌套

这一步,我们在升级一下。加一个函数的嵌套,说白了就是在一个函数中定义一个新的函数。

def func1(func): print("This is func1") def insidefunc(): print("This is the inside function") func() print("Inside function end") print("func1 end\n") return insidefunc def func2(): print("This func2") print("func2 end\n") print("start:") print("func2 name:", func2.__name__, "\n") print("To decorate:") func2 = func1(func2) print("end:") print("func2 name", func2.__name__, "\n") func2()

能够理解以上代码,其实就基本理解装饰器了 他主要就是将func2变成另一个函数而已。 执行结果:

3.运用装饰器

好了我们开始运用装饰器吧

def func1(func): print("This is func1") def insidefunc(): print("This is inside function") func() print("Inside function end") print("func1 end\n") return insidefunc @func1 def func2(): print("This is func2") print("func2 end") print("start:") print("func2 name:", func2.__name__) func2()

我们先来看一下执行效果: 从结果可以看到,当我们在修饰时,就已经调用好了修饰函数func1修饰了,之后在调用的时候就不在调用修饰函数func1了。这里要注意的是,我们在定义修饰函数时必须在内部定一个新的函数insidefunc,然后在这个新的函数中进行操作后,最后返回这个insidefunc,也就是说func2已经变成了insidefunc了

4.被修饰的函数传入参数

当然,我们的被修饰函数是可以传入函数的。只不过我们需要在修饰函数的内部函数insidefunc的()的参数与被修饰函数的参数数量一致就好。

def func1(func): print("This is func1") def insidefunc(a, b): print("This inside function") a = func(a, b) print("Parameter from func:", a) print("Inside function end") print("func1 end\n") return insidefunc @func1 def func2(a, b): print("This is func2") print("func2 end") return a + b print("start") func2(4, 5)

5.修饰函数传入参数

我们的修饰函数也是可以传入参数的

def func1(arg=True): if arg: def _func1(func): print("This in _func1") def insidefunc(a, b): print("This is in _func1.insidefunc") c = func(a, b) return c return insidefunc return _func1 else: def _wfunc1(func): print("This is _wfunc1") return func return _wfunc1 @func1(True) def func2(a, b): print("This func2") return a + b @func1(False) def func3(a, b): print("This is func3") return a * b print(func2(4, 5)) print("\n") print(func3(4, 5))

6.装饰器的连续套用

def func1(func): def _func1(a): print("This is _func1") a = func(a) return a * a return _func1 def func2(func): def _func2(a): print("This is _func2") a = func(a) return a * 3 return _func2 @func1 @func2 def func3(a): print("This is func3") return a print("Start:") print(func3(1)) print(func3(2))


还有一些其他装饰器的用法,比如在类里面装饰函数,或者用类来装饰就不一一展开了

三.装饰器的主要用途

说了这么多,大家可能对装饰器到底在实际开发中有什么应用还是很困惑的。其实在实际的开发中,装饰器还是很常见的,而且用处还很大。 主要应用于几个方面:参数检查、统计时间、缓存、注册回调函数、函数加日志 、线程异步等等 举个例子多线程异步:

from threading import Thread from functools import wraps def async(func): @wraps(func) def async_func(*args, **kwargs): func_hl = Thread(target=func, args=args, kwargs=kwargs) func_hl.start() return func_hl return async_func if __name__ == '__main__': from time import sleep @async def print_somedata(): print('starting print_somedata') sleep(2) print('print_somedata: 2 sec passed') sleep(2) print('print_somedata: 2 sec passed') sleep(2) print('finished print_somedata') @async def _print_somedata(): print('starting _print_somedata') sleep(2) print('_print_somedata: 2 sec passed') sleep(2) print('_print_somedata: 2 sec passed') sleep(2) print('finished _print_somedata') def main(): print_somedata() print('back in main') _print_somedata() print('back in main') main()

详细用途可以看看官方文档:https://wiki.python.org/moin/PythonDecoratorLibrary


好了,今天就到这。谢谢浏览。 有问题探讨加QQ:1043601529。

转载请注明原文地址: https://www.6miu.com/read-1450214.html

最新回复(0)