python中的装饰器和java的注解在外观上很像。python中,装饰器本质上是一个类或一个带有返回类型为函数的高阶函数。
装饰器可以扩展一个类或函数的功能。有关装饰器的详细介绍,推荐查看文章“Python装饰器注解”
下面讲讲python中装饰器的本质,我在bilibili上找到一个讲的很好的一个视频,链接是:
【python】装饰器超详细教学,用尽毕生所学给你解释清楚,以后再也不迷茫了!_哔哩哔哩_bilibili
- def dec(f):
- pass
-
- @dec
- def double(x):
- return x *2
-
- #上面double函数上增加注解后,完全等价于下面的写法
- double = dec(double)
可以看到,装饰器本质上是一个返回类型为函数的高阶函数。当在一个普通函数上增加注解,则本质上系统会调用装饰器函数dec,参数为函数对象double,然后装饰器函数返回一个函数对象,并赋值给一个跟函数名同名的对象double。
例子1: 下面看一个实际的例子
- def timeit(f):
-
- def wrapper(x):
- start = time.time()
- ret = f(x)
- print(time.time() - start)
- return ret
-
- return wrapper
-
-
- @timeit
- def my_func(x):
- time.sleep(1)
-
-
- if __name__ == '__main__':
- my_func(1)
运行后输出
1.005021095275879
编译器运行到下面代码的时候
- @timeit
- def my_func(x):
- time.sleep(1)
所以其本质是运行了
my_func = timeit(my_func)
所以当调用my_func(1)时,实际上是在执行wrapper(1)。
例子二:注解上还可以增加注解
看看下面的代码运行结果是什么
- import time
-
-
- def timeit(f):
-
- def wrapper(x):
- start = time.time()
- ret = f(x)
- print(time.time() - start)
- return ret
-
- return wrapper
-
- @timeit
- @timeit
- def my_func(x):
- time.sleep(1)
-
-
- if __name__ == '__main__':
- my_func(1)
运行后结果为:
- 1.0050477981567383
- 1.0051438808441162
编译器运行到下面代码时
- @timeit
- @timeit
- def my_func(x):
- time.sleep(1)
实际上执行了my_func=timeit(timeit(my_func))
例子3: 装饰器有参数
看看下面代码
- import time
-
-
- def timeit(k):
-
- def inner(f):
-
- def wrapper(x):
- start = time.time()
- for _ in range(k):
- ret = f(x)
- print(time.time() - start)
- return ret
-
- return wrapper
-
- return inner
-
- @timeit(2)
- def my_func(x):
- time.sleep(1)
-
-
- if __name__ == '__main__':
- my_func(1)
其中
- @timeit(2)
- def my_func(x):
- time.sleep(1)
本质上变成了
my_func = timeit(2)(my_func)