装饰器
本质: 语法糖( 实现闭包的一种语法糖 )
- @set_func —> test = set_func(test)
- 返回一个闭包
作用: 在不修改原函数的情况下, 对函数的功能进行添加; 提高代码可复用性的作用
何时运行: 只要遇到这句话就解析, 直接装饰( 在函数调用之前就已经装饰 )
应用
多层装饰: 像快递包裹: 包裹从内往外, 拆包从外往内
装饰顺序: 先判断下面是否为函数, 如果是函数才装饰;
- 找到以后, 从下往上装饰
调用顺序: 从上往下拆 (与装饰相反)
- 装饰时: 从下往上
- 调用时: 从上往下
(被装饰的函数) 参数问题:
无参数 : def inner():
有参数: def inner( *args, **kwagrs ):
def set_func(func): def call_func(*args, **kwargs): # func(args, kwargs) # 不行, 相当于传递了2个参数: 1个字典,1个元组 func(*args, **kwargs) # 拆包 return call_func
(被装饰的函数) return问题:
def inner():
- return func()
装饰器带有参数:
- 执行过程:
- 调用魔法糖 并且将 其上写的参数 当做实参传递
- 用上一步调用的返回值 当做 装饰器 , 对下面的函数进行装饰
def set_level(level_num): def set_func(func): def call_func(*args, **kwargs): if level_num == 1: print("----authority level 1----") else: level_num == 2: print("----authority level 2----") return func() return call_func return set_func @set_level(1) # 调用set_level,并且将1当做实参传递;用它的返回值当做装饰器 def test1(): print("----test1----") return "ok" @set_level(2) def test2(): print("----test2----") return "ok" test1() test2()
类装饰器
class Test(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
@Test # get_str = Test(get_str)
def get_str():
return "hah"
print(get_str())
闭包(轻度封装)
三要素:
- 使用了嵌套函数
- 外部函数返回内部函数的引用
- 内部函数使用了外部函数的变量或参数
对比:
匿名函数: 能够完成 简单的功能, 只有功能
普通函数: 能够完成 较为复杂的功能, 只有功能
闭包: 能够完成 较为复杂的功能, 有功能 + 数据(函数仅仅有功能,闭包还有需要的数据)
闭包与函数的区别: 函数: 仅仅具有功能 闭包: 不仅仅具有功能, 还有需要的数据 闭包中修改变量: 全局变量: global 内部函数修改外部函数局部变量: nonlocal
- 对象: 能够完成 较为复杂的功能, 有很多数据, 很多功能 功能 + 数据
闭包: 比函数多一些 特殊的数据(外部的全局变量), 比对象更小, 只有小部分数据 和 一段代码; 可以理解为轻量级的面向对象
进阶:
闭包 与 普通函数加上一个全局变量 的区别
闭包: 每一个闭包拥有自身独立的变量(轻度封装), 个人是个人,互不影响
全局+函数: 当在定义一个函数时,共享全局变量, 一方改变, 另一方立马就废了