一文读懂装饰器
您是否有这样的烦恼?
研究很长时间装饰器了但是还不明白装饰器是什么东西?
明明上次感觉有点眉目了,但是感觉没内味。
今天希望通过这篇文章能让您知道装饰器到底是什么?
在这之前您需要了解闭包(在这里我就不多赘述,大家自行百度)
装饰器能干什么?
装饰器模式(Decorator
Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
简单一点说就是在原有函数基础上添加方法,让被装饰的函数运行装饰函数的代码。
这里有一个例子:
import time
# 是否为质数
def is_prime(num):
if num < 2:
return False
elif num == 2:
return True
else:
for i in range(2, num):
if num % i == 0:
return False
return True
# 计算时间
def prime_nums():
t1 = time.time()
for i in range(2, 10000):
if is_prime(i):
print(i)
t2 = time.time()
print(t2 - t1)
prime_nums()
从上面代码可以看出prime_nums既有逻辑的部分(打印质数),也有计算时间的部分所以可以看出代码可读性非常的低,想要变这样的问题需要用到装饰器。
这段代码等同于将计时与操作分开写,之后利用装饰器的特性将两段代码结合起来
import time
# func等同于我等一下要运行这个函数
def diaplay_time(func):
# 该函数表示要运行哪些内容
def wrapper():
t1 = time.time()
# 这里表示运行函数-->装饰谁就运行谁
func()
t2 = time.time()
print(t2 - t1)
return wrapper
def is_prime(num):
if num < 2:
return False
elif num == 2:
return True
else:
for i in range(2, num):
if num % i == 0:
return False
return True
# 装饰这段代码也就意味着func=prime_nums()
@diaplay_time
def prime_nums():
for i in range(2, 10000):
if is_prime(i):
print(i)
prime_nums()
这样您就学会了装饰器的基础操作了,但是我们需要参数应该怎么办?
import time
# func等同于我等一下要运行这个函数
def diaplay_time(func):
# 该函数表示要运行哪些内容(如果装饰的函数需要参数需要在函数内写入参数)
def wrapper(*args):
t1 = time.time()
# 这里表示运行函数-->装饰谁就运行谁 (这里也需要将参数放进去)
result = func(*args)
t2 = time.time()
print(t2 - t1)
# 如果装饰的函数有返回值,那么这里也需要进行返回
return result
return wrapper
def is_prime(num):
if num < 2:
return False
elif num == 2:
return True
else:
for i in range(2, num):
if num % i == 0:
return False
return True
@diaplay_time
# 这里需要传入参数需要在上面进行一些定义
def count_prime_nums(max_num):
count = 0
for i in range(2, max_num):
if is_prime(i):
count += 1
return count
# 这里写入需要传的参数 参数传递过程: 10000-->*args-->func(*args)-->count_prime_nums(max_num)
nums = count_prime_nums(10000)
print(nums)
这样的操作也可以运用到Django的验证用户是否登录的装饰器(虽然上下文能解决,但是有的面试官还是要问)
这个就不做过多的解释了
def check_login(func): # 自定义登录验证装饰器
def warpper(request, *args, **kwargs):
is_login = request.session.get('is_login', False)
if is_login:
func(request, *args, **kwargs)
else:
return redirect("/login")
return warpper
这就是装饰器了
另外附上学习的地址:
https://www.bilibili.com/video/av25698102