python 装饰器 参数-Python装饰器(4)带参数的装饰器

内容纯属个人理解,不对之处,欢迎指正。

之前说过,装饰器其实就是函数,既然是函数,那就可以有参数,装饰器也不例外,接下来我们来分析带参数的装饰器。

如何构造带参数

带参数倒是很简单,在装饰的时候给装饰函数写上参数就行,但是具体的装饰器函数该怎么写,我们需要思考一下。

我们想让它带参数,无非就是对被装饰函数的执行进行一定条件的限定设置,也就是说在函数执行之前,函数就必须具备这个条件,那么这样的话,就有两种选择,要么在传递func以后传递参数;要么在传递func之前传递参数。

在想法上,两种其实是都可以的,但是,我们传递参数的时候是给装饰器传递,也就是说,装饰器函数首先接收的是装饰器函数的参数,然后带着这个参数再去装饰函数。因此,我们就必须先处理装饰器函数的参数,然后再去处理被装饰的函数。

所以在实现上,我们应该这样去构造带参装饰器函数:

def deco_para(parameter):

def deco_func(func):

def wrapper(*args, **kwargs):

print(parameter)

func(*args, **kwargs)

return wrapper

return deco_func

带参装饰器示例

def deco_para(parameter):

print('enter deco_para')

def deco_func(func):

print('enter deco_func')

def wrapper(*args, **kwargs):

print('enter wrapper')

print(parameter)

print('---wrapper: before func---')

func(*args, **kwargs)

print('---wrapper: after func---')

return wrapper

return deco_func

@deco_para(123)

def foo():

print('---foo---')

if __name__ == '__main__':

print('--start--')

foo()

运行结果:

enter deco_para

enter deco_func

--start--

enter wrapper

123

---wrapper: before func---

---foo---

---wrapper: after func---

结果应该不用多说,先接收参数123,然后接收函数foo,最后执行wrapper。

装饰过程解析--多次输出问题

我们解析下过程

deco_func = deco_para(123) # 接收参数123

wrapper = deco_func(foo) # 接收函数foo

foo = wrapper # 重命名

foo() # 执行foo

如果你试着按这个过程去执行代码,会发现一个问题,wrapper函数里面的代码执行了2次。

enter deco_para

enter deco_func

enter deco_para

enter deco_func

enter wrapper

123

---wrapper: before func---

enter wrapper

123

---wrapper: before func---

---foo---

---wrapper: after func---

---wrapper: after func---

我们看下究竟是怎么回事。

# 程序执行,扫面到装饰器,执行装饰器函数内部代码

1.enter deco_para

2.enter deco_func

# deco_para(123)接收参数123时执行3

3.enter deco_para

# deco_func(foo)接收函数foo时执行4

4.enter deco_func

# foo()执行foo()

5.enter wrapper

6.123

7.---wrapper: before func---

8.enter wrapper

9.123

10.---wrapper: before func---

11.---foo---

12.---wrapper: after func---

13.---wrapper: after func---

在之前解析装饰器的时候就提到过,函数被装饰以后,就不是原来的函数了,也就是说上面所执行的foo,其实是wrapper。

那么wrapper里面有什么东西呢?

print('enter wrapper')

print(parameter)

print('---wrapper: before func---')

func(*args, **kwargs)

print('---wrapper: after func---')

似乎执行结果应该是

enter wrapper

123

---wrapper: before func---

---foo---

---wrapper: after func---

但是事实上,此时的wrapper里面的func已经不是原来的func。

回顾闭包:引用了自由变量的函数即是一个闭包,这个被引用的自由变量和这个函数一同存在, 即使已经离开了了创造它的环境也不例外。

那么可以推测,此时的被装饰函数应该具有了额外的东西,这些东西就是

print('enter wrapper')

print(parameter)

print('---wrapper: before func---')

print('---wrapper: after func---')

由此也就可以知道为什么wrapper里面的代码执行了2次:就是在执行到func(*args, **kwargs)的时候,执行了功能丰富以后的func。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值