装饰器@
装饰器就是用一个函数A去修饰一个函数B,可以使得A,B代码分离,逻辑上更清晰。比如我们要计算判断素数所使用的的时间,一般会写成如下代码:
import time
def is_prime(n):
if n == 2:
return True
else:
for i in range(2, n):
if n % i == 0:
return False
return True
def prime():
t1 = time.time()
for i in range(2, 1000):
if is_prime(i):
print(i)
else:
pass
t2 = time.time()
print(t2 - t1)
prime()
用装饰器可以将计算时间的代码抽离出来,如下:
import time
def calculate_time(func):
def wrapper():
t1 = time.time()
func()
t2 = time.time()
print(t2 - t1)
return wrapper
def is_prime(n):
if n == 2:
return True
else:
for i in range(2, n):
if n % i == 0:
return False
return True
@calculate_time
def prime():
for i in range(2, 1000):
if is_prime(i):
print(i)
else:
pass
prime()
两者在效果上是一样的,而且计算时间的装饰器可以多次使用在不同函数上。
带参数的函数装饰器
函数需要传入参数,只需要在wrapper()传入*args即可。以判断素数为例,假设我们需要判断2-10000之间的素数,代码如下:
import time
def calculate_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
func(*args, **kwargs)
t2 = time.time()
print(t2 - t1)
return wrapper
def is_prime(n):
if n == 2:
return True
else:
for i in range(2, n):
if n % i == 0:
return False
return True
@calculate_time
def prime(num):
for i in range(2, num):
if is_prime(i):
print(i)
else:
pass
prime(10000)
带返回值的函数装饰器
假设我们现在需要统计1000以内的素数数量,可以如下书写代码:
import time
def calculate_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
count = func(*args, **kwargs)
t2 = time.time()
print(t2 - t1)
return count
return wrapper
def is_prime(n):
if n == 2:
return True
else:
for i in range(2, n):
if n % i == 0:
return False
return True
@calculate_time
def prime(num):
count = 0
for i in range(2, num):
if is_prime(i):
print(i)
count += 1
else:
pass
return count
total_count = prime(1000)
print("1000以内的素数数量为:", total_count)
多个装饰器嵌套
假设有三个装饰器,代码如下:
'''
多个装饰器装饰一个函数
定义阶段:自下而上加载;
执行阶段:自上而下运行;
'''
# 定义第一个装饰器
def set_func1(func):
print("set_func1")
def wrapper1(*args, **kwargs):
print('装饰内容开始1')
func(*args, **kwargs)
print('装饰内容结束1')
return wrapper1
# 定义第二个装饰器
def set_func2(func):
print("set_func2")
def wrapper2(*args,**kwargs):
print('装饰内容开始2')
func(*args, **kwargs)
print('装饰内容结束2')
return wrapper2
# 定义第二个装饰器
def set_func3(func):
print("set_func3")
def wrapper3(*args, **kwargs):
print('装饰内容开始3')
func(*args, **kwargs)
print('装饰内容结束3')
return wrapper3
@set_func1
@set_func2
@set_func3
def show():
print('Show Run....')
# show()
# 结果如下:
# 装饰内容开始1
# 装饰内容开始2
# 装饰内容开始3
# Show Run....
# 装饰内容结束3
# 装饰内容结束2
# 装饰内容结束1
#
# 进程已结束,退出代码 0
多个装饰器修饰一个函数时,定义(加载阶段)自下而上,注释show()运行的结果如下:
set_func2
set_func1
执行代码阶段是自上而下运行的,运行show()得到的结果如下:
set_func2
set_func1
装饰内容开始1
装饰内容开始2
装饰内容开始3
Show Run…
装饰内容结束3
装饰内容结束2
装饰内容结束1
运行阶段包括了加载,此时
即先运行装饰器set_func1,执行到show函数时,执行
也就是开始执行装饰器set_func2,如此下去,相当于递归。