文章目录
一、引言
装饰器是每一个使用Python的人都会接触到的一种增强函数功能的方式,也是面试官经常会问到的知识点,这里通过一个函数运行时间的装饰器,举例说明常见的四种装饰器实现方法
装饰器的概念
装饰器是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic
装饰器实际上也是一个函数 ,这个函数以闭包的形式定义,而我们知道在Python中万物皆对象,即函数也是一个对象,而且函数对象可以被赋值给变量,所以将原函数作为变量传递给装饰器函数,就能够给原函数添加装饰器中的功能
这里举一个最简单的装饰器例子:
def decorator(func):
def wrapper(*args, **kwargs):
print("decorator sentence")
func(*args, **kwargs)
return wrapper
@decorator
def hello():
print("hello world")
hello()
>>>decorator sentence
>>>hello world
decorator
方法接收一个函数作为参数,使用@decorator
装饰hello
函数之后,相当于执行了hello = decorator(hello)
而decorator
方法return wrapper
,因此被装饰后执行的hello()
相当于执行了wrapper()
这里wrapper(*args, **kwargs)
接收所有的参数,并把参数传递给func
形参对应的函数(也就是hello
函数)执行
二、用装饰器装饰函数
1、函数装饰器
在面试中,面试官考察面试者对于装饰器的基本掌握水平,常常会让面试者手写一个简单装饰器,其中写一个打印方法执行时间的装饰器是最有可能出现的问题之一
这里就以实现一个打印方法执行时间的装饰器为例
import time
def calculate_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print("Function run time is: ", end - start)
return result
return wrapper
@calculate_time
def test_func(time_val):
time.sleep(time_val)
print("Function sleep %s second" % time_val)
return "end"
if __name__ == '__main__':
test_func(2)
这个例子中wrapper(*args, **kwargs)
接收任意参数,而且将函数test_func
执行结果return
,实现的是有参有返的装饰器(这里的有参有返指的是原函数有参有返)。
虽然代码最后并没有用到原test_func
的返回结果,写成有参有返只是想展现一种比较全能的装饰器格式。
结果(后面结果相同):
Function sleep 2 second
Function run time is: 2.0045318603515625
2、带参数的函数装饰器
在实际开发中,我们的装饰器往往需要接收参数,根据传入装饰器的参数不同实现不同功能,那就需要编写一个返回decorator的高阶函数,写出来会更复杂
import time
def calculate_time(time_val): # time_val为装饰器接收的参数
def