装饰器
装饰器的概念:
可以在不修改原来代码的情况下(函数原有的功能)的情况下,为装饰器的对象(原来的函数)增加
新的功能或者添加限制条件以及帮助输出
装饰器的常用的种类:
- 函数的装饰器
- 类的装饰器
- 主要的设计模式:开放封闭的原则(对外扩展开发,对内关闭修改)
1.1装饰器的定义
- 装饰器本身是一个函数
- 装饰器的返回值是一个函数的引用(函数名字)
- 装饰器只能必须一定是一个形参(形参:用来接收函数的引用(接收函数的名字))
核心的使用原则:装饰器是给已有的函数增加额外的功能,本质上是一个闭包函数
装饰器的功能特点:
- 不修改被装饰的函数原代码
- 不修改已有函数的调用方式
- 给已有函数增加额外功能(通过函数外部的装饰器实现)
例:场景:去京东购物,先登录才能添加商品到购物车
# 场景:去京东购物,先登录才能添加商品到购物车
# 定义一个装饰器帮助购物之前完成登录操作
def check(fn): # fn: 装饰器只能必须一定是一个形参(形参:用来接收函数的引用(接收函数的名字))
# fn = shopping:fn接收了shopping函数的引用
def inner():
print("开始进入登录页面")
print("输入账号密码点击登录")
print("正在进行验证.......")
print("登录成功")
fn() # fn函数的引用: fn = shopping ---> fn() = shopping()
return inner
def shopping():
print("买一条大金链子")
shopping = check(shopping) # shopping = inner
shopping() # shopping() = inner()代码流程:7--8--9--10--11--12---17--18
# in2 = check(shopping) # in2 = inner
# in2() # in2() = inner()代码流程:7--8--9--10--11--12---17--18
代码执行步骤流程:
1.2装饰器的语法糖使用
- Python提供了装饰器的精简的书写方式:语法糖格式
- @装饰器的名字,通过语法糖完成对已有函数的装饰
- 注意:装饰器要写在被装饰的函数定义的上面
def check(fn): # fn: 装饰器只能必须一定是一个形参(形参:用来接收函数的引用(接收函数的名字))
# fn = shopping:fn接收了shopping函数的引用
def inner():
print("开始进入登录页面")
print("输入账号密码点击登录")
print("正在进行验证.......")
print("登录成功")
fn() # fn函数的引用: fn = shopping ---> fn() = shopping()
return inner
# shopping等同于一个变量名字 = check(shopping(指向的是被装饰的函数名字)等同于fn)
@check # shopping = check(shopping)
def shopping():
print("买一条大金链子")
shopping()
说明:
- @check等同于shopping = check(shopping)
- 解释器在执行代码的时候遇到装饰器先加载装饰器代码并执行
def check(fn): # fn: 装饰器只能必须一定是一个形参(形参:用来接收函数的引用(接收函数的名字))
# fn = shopping:fn接收了shopping函数的引用
def inner():
print("开始进入登录页面")
print("输入账号密码点击登录")
print("正在进行验证.......")
print("登录成功")
fn() # fn函数的引用: fn = shopping ---> fn() = shopping()
print("装饰器代码已经开始执行了....")
return inner
小结:装饰器本质上就是一个闭包函数,只不过传递过去的实参是被装饰函数的引用
1.3带有参数的装饰器
用装饰器完成符号传递实参进行运算
# 用装饰器完成符号传递实参进行运算
# 实现思路:在原有不带参数的装饰器上面再嵌套一层函数用来接收装饰器的参数
def mark(flag): # flag:接收装饰器的实参
def out_func(fn):
def inner_func(nmu1, num2):
if flag == "+":
print("你输入的符号是加号,正在努力计算中......")
elif flag == "-":
print("你输入的符号是减号,正在努力计算中......")
result = fn(nmu1, num2)
return result
return inner_func
return out_func
# 带有参数的装饰器代码执行流程:
# 19:-----3-----15-----4-----13------5-----6-----7-----10-----11-----31
@mark("+")
def jiafa(a, b):
result = a + b
return result
@mark("-")
def jianfa(a, b):
result = a - b
return result
print(jiafa(1, 9))
print(jianfa(1, 9))
1.4装饰器的使用场景
- 统计一个函数的执行时间
- 输出日志信息
- 缓存处理
- 实现路由
例:统计一个函数的执行时间案例实现
# 定义一个装饰器
def get_time(func):
def inner():
begin = time.time()
func()
end = time.time()
print(f"当前模块代码执行的时间是:{end - begin}")
return inner
@get_time
def fn():
for i in range(1, 3000000):
print(i)
fn()