文章目录
Python中装饰器的使用
装饰器的定义
装饰器的使用
多个装饰器的调用
Python中装饰器的使用
在软件开发过程中,不同的阶段设计开发时会定义一些函数,而后期的开发过程中,希望扩展一些装饰这个函数的内容,即装饰器;举例如下
存在一个计算两个数相加的函数
def add(a , b):
'''
求任意两个数的和
'''
r = a + b
return r
res = add(123,456)
print(res)
执行结果:
579
希望在执行这个计算前程序输出"计算开始…";计算时输出"计算结束…" 前提是不能改变原函数;如下所示
#定义一个函数,达到需求的设计
def new_add(a,b):
print('计算开始~~~')
r = add(a,b)
print('计算结束~~~')
return r
r = new_add(111,456)
print(r)
执行结果
计算开始~~~
计算结束~~~
567
以上的设计虽然完成了需求,但是相对应的也带来了一些问题
如果要修改的函数过多,修改起来会比较麻烦
并且不方便后期的维护
并且这样做会违反开闭原则(OCP)
OCP: Open Control Principle 程序的设计,要求开放对程序的扩展,要关闭对程序的修改
为了解决这个问题,创建一个可以自动的生产函数
装饰器的定义
# 用于计算两个数相加
def add(a,b):
r = a+b
return r
# 用于计算两个数相乘
def mul(a,b):
r = a*b
return r
def decorators(fun):
'''
这是一个装饰器函数
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
**参数:
fun 要扩展的函数对象
'''
# 创建一个新函数
'''
*args 用于接收所有的位置参数
**kwargs 用于接受所有的关键字参数
'''
def new_fun(*args,**kwargs): #将参数装包成元组或字典
print('计算开始...')
# 调用被扩展的函数
num = fun(*args,**kwargs) #将元组拆包成位置参数,将字典拆包成关键字参数
print('计算结束...')
# 返回函数的执行结果
return num
# 返回新函数
return new_fun**
# 调用
r = decorators(add) # 将装饰器函数的返回值函数,即内部的函数给到r
print(r) # r就是装饰器函数的内部函数的内存地址
res = r(123,456) # 向内部函数传参,相当于add(123,456)
print(res)
执行结果
<function decorators.<locals>.new_fun at 0x0000016AFFFB6950>
计算开始...
计算结束...
579
计算两个数相乘的情况,如下调用
扫描二维码关注公众号,回复:
15254862 查看本文章
r = decorators(add)
print(r)
res = r(123,456)
print(res)
print('-'*30)
r = decorators(mul)
print(r)
res = r(2,3)
print(res)
执行结果
<function decorators.<locals>.new_fun at 0x000001D00B7168C8>
计算开始...
计算结束...
579
------------------------------
<function decorators.<locals>.new_fun at 0x000001D00B716950>
计算开始...
计算结束...
6
可见,每次调用装饰器函数的内部函数时,分配的内存肯定是不一样的,传入的add、mul实参就是真实计算的函数内容
装饰器的使用
- 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
- 在开发中,我们都是通过装饰器来扩展函数的功能的
- 在定义函数时,可以通过@装饰器,来使用指定的装饰器,来装饰当前的函数
如下所示:函数装饰器的内容不变,只是在定义函数的时候加上@装饰器函数的名称即可
但是这样一来,装饰器就与函数实体进行了绑定,以后调用函数时都会携带装饰器
def decorators(fun):
'''
这是一个装饰器
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
fun 要扩展的函数对象
'''
# 创建一个新函数
'''
*args 用于接收所有的位置参数
**kwargs 用于接受所有的关键字参数
'''
def new_fun(*args,**kwargs): #将参数装包成元组或字典
print('计算开始...')
# 调用被扩展的函数
num = fun(*args,**kwargs) #将元组拆包成位置参数,将字典拆包成关键字参数
print('计算结束...')
# 返回函数的执行结果
return num
# 返回新函数
return new_fun
# 对函数实体进行装饰
@decorators
def add(a,b):
r = a+b
return r
@decorators
def mul(a,b):
r = a*b
return r
# 调用
res = add(123,456)
print(res)
print('-'*30)
res = r(2,3)
print(res)
计算开始...
计算结束...
579
------------------------------
计算开始...
计算结束...
6
多个装饰器的调用
- 可以同时为一个函数指定多个装饰器
- 函数将会安装从内向外的顺序被装饰
def fn1(fun):
def new_function(*args , **kwargs):
print('fn1装饰~开始执行~~~~')
result = fun(*args , **kwargs)
print('fn1装饰~执行结束~~~~')
return result
return new_function
def fn2(fun):
def new_function(*args , **kwargs):
print('fn2装饰~开始执行~~~~')
result = fun(*args , **kwargs)
print('fn2装饰~执行结束~~~~')
return result
return new_function
@fn1
@fn2
def say_hello():
print('大家好~~~')
say_hello()
由内到外的执行就是,以say_hello()函数的输出结果为中心,先使用fn2装饰器,然后使用fn1装饰器
执行结果
fn1装饰~开始执行~~~~
fn2装饰~开始执行~~~~
大家好~~~
fn2装饰~执行结束~~~~
fn1装饰~执行结束~~~~
改变顺序
@fn2
@fn1
def say_hello():
print('大家好~~~')
say_hello()
执行结果
fn2装饰~开始执行~~~~
fn1装饰~开始执行~~~~
大家好~~~
fn1装饰~执行结束~~~~
fn2装饰~执行结束~~~~