浅谈装饰器
装饰器:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
装饰器原则:
- 不能修改被装饰的函数的源代码
- 不能修改被装饰的函数的调用方式
实现装饰器知识储备:
- 函数即“变量”
- 高阶函数
- 嵌套函数
例子1:声明普通函数
def func():
print("我是秃头儿")
# 简单的函数调用
func()
# 打印结果:我是秃头儿
# 打印func函数的内存地址
print(func) # <function func at 0x000001E2B58D9BF8>
- 给上面的函数加一个装饰器
例子2:装饰器普通语法
def outer(fn):
def inner():
fn()
# 打印inner函数的内存地址
print(inner) # <function outer.<locals>.inner at 0x000002A2BE029E18>
return inner
@outer
def func():
print("我是秃头儿")
func()
# 打印func函数的内存地址
print(func) # <function outer.<locals>.inner at 0x000002A2BE029E18>
-
声明函数func前面加上 @outer
-
在调用函数func时,相当于 func = outer(func)
-
此时的func函数的内存地址发生了变化,变成outer函数的内部inner函数的内存地址
例子3:函数带一个参数装饰器的写法
def outer(fn):
print("我要买假发~")
def inner(money):
print("支付了{}块钱!".format(money))
fn(money)
print("购买完成!")
print("啦啦啦~我头上有头发啦!!!")
return inner
@outer
def func(money):
print("我是秃头儿")
func(100)
# 打印结果
# 我要买假发~
# 支付了100块钱!
# 我是秃头儿
# 购买完成!
# 啦啦啦~我头上有头发啦!!!
- 上面的例子只是一个参数。
- 倘若要传多个参数,多个参数之中存在整型、字符串、列表、字典等。
- 这样子写法是不合适的
例子4:函数形参不定参数的写法
def outer(fn):
print("我要买假发~")
def inner(*args, **kwargs):
print("假发的颜色有{}".format(args[1]))
print("支付了{}块钱!".format(args[0]))
fn(args)
print("购买完成!")
print("啦啦啦~我头上有头发啦!!!")
return inner
@outer
def func(*args, **kwargs):
print("我是秃头儿")
color = ["黄色", "蓝色", "绿色"]
func(100, color)
# 打印结果
# 我要买假发~
# 假发的颜色有['黄色', '蓝色', '绿色']
# 支付了100块钱!
# 我是秃头儿
# 购买完成!
# 啦啦啦~我头上有头发啦!!!
- 上面的代码看上去比"例3"强大了许多
- 如果在装饰器函数加一个形参
- 又该怎么办?
例5:在装饰器函数加形参
def decorator(address):
print("在{}里有卖。".format(address))
def outer(fn):
print("我要买假发~")
def inner(*args, **kwargs):
print("假发的颜色有{}".format(args[1]))
print("支付了{}块钱!".format(args[0]))
fn(args)
print("购买完成!")
print("啦啦啦~我头上有头发啦!!!")
return inner
return outer
@decorator("理发店")
def func(*args, **kwargs):
print("我是秃头儿")
color = ["黄色", "蓝色", "绿色"]
func(300, color)
# 打印结果
# 在理发店里有卖。
# 我要买假发~
# 假发的颜色有['黄色', '蓝色', '绿色']
# 支付了300块钱!
# 我是秃头儿
# 购买完成!
# 啦啦啦~我头上有头发啦!!!
- 要是给装饰器加了一个形参。
- 就在原来的装饰器外添加一层函数。
- 最终达到三层函数嵌套。
注:如果一个函数有多个装饰器, 首先执行离它最近的那个装饰器
**例6:**多层装饰器
def supermarket(fn):
print("---------> 2:start")
def buy(*args, **kwargs):
fn()
print('我戴着假发逛超市')
print("---------> 2:end")
return buy
def outer(fn):
print("---------> 1:start")
def inner(*args, **kwargs):
print("我要买假发~")
fn()
print("购买完成!")
print("---------> 1:end")
return inner
@supermarket
@outer
def func(*args, **kwargs):
print("我是秃头儿")
func()
# 打印结果
# ---------> 1:start
# ---------> 1:end
# ---------> 2:start
# ---------> 2:end
# 我要买假发~
# 我是秃头儿
# 购买完成!
# 我戴着假发逛超市