装饰器:
应用广泛,依赖闭包,是在闭包的基础上的升级
def decorate(func): # 定义一个装饰器
a = 100
def wrapper(): # 包装 装饰
func() # 调用被装饰函数,保持其原功能
print(' wrapper print a :', a)
return wrapper
decorate(xxx) # 传入函数名 作为参数
注释:func是一个函数,decorate()传入参数为函数
装饰器的使用:
在被装饰的函数上面加上@装饰器名
# 使用装饰器
@decorate
def house():
print('i am 毛坯房')
house()
注释:@decorate——装饰器,house()——被装饰函数
假如在开发完成后,发现house()函数还有不足,需要丰富一下。
-
更改原函数 – 不可取
-
不一定所有调用原函数都需要更改
-
-
新增一个函数 – 不可取
-
需要改 原来调用 house()的代码
-
装饰器 在不改变原函数名、原函数体的情况下,对函数功能进行修改
# 完整
def decorate(func): # 定义一个装饰器
a = 100
print('wrapper 外层打印 仍然 执行 ')
def wrapper(): # 包装 装饰
print(' wrapper print a :', a)
func()
print(' 装饰器在原函数的基础上,增加了一个 a:{} 的输出 '.format(a))
print('即使不调用,由于@decrator,wrapper 外层打印 仍然执行 ')
return wrapper
# 使用装饰器
@decorate
def house():
print(' house() :i am 毛坯房, 原函数,保持原功能')
# house() # 底层是将wrapper付给了house
-
@decrator 步骤分析
- 将其下方函数,作为参数 传给decrator()
- 底层 默执行decrator()函数里面的代码
- 执行到 wrapper(), 加载wrapper内容(未执行)
- 最后 return wrapper
- 默认 同名的house 接收 返回的wrapper
- 打印 wrapper 地址id
- 打印 此时的 新house 地址id
- 下面的新house 即为 wrapper, 其中调用了原house
装饰器参数:
wrapper 也传入同样参数即可:
def decorate(func): # 定义一个装饰器
def wrapper(x): # 包装 装饰
func(x) # 调用被装饰函数,保持其原功能
print(' wrapper print a :', a)
return wrapper
万能 传入参数
使用可变参数
def decorate(func): # 定义一个装饰器
def wrapper(*args, **kwargs): # 包装 装饰
func(*args, **kwargs) # 调用被装饰函数,保持其原功能
print(' wrapper print a :', a)
return wrapper
多层装饰器:
@decorate2
@decorate1
house()
首先 近的decorate1 生效,
然后 decorate2 生效
- 可以分析:
- decorate2先装饰完
- decorate1装饰 被 decorate2 装饰过的house
- 调用的是 被decorate1 装饰过的 house
- 相当于 func(func1(func2()))
带参数的装饰器