装饰器依赖知识点:
1、什么是装饰器
器即工具,多数情况下指的是函数;装饰指的是为其它代码添加额外的功能!Python装饰器可以对函数、类、方法进行加工处理,以达到某种目的!
2、为何要用装饰器
在线上业务环境中,一般情况下我们写好的代码是不会随便变更的,线上直接修改代码保不准你改的代码会有BUG或者引起连锁反应,影响业务的正常运转!但有时候又想在不改动源代码的前提下,为其新增功能,有没有办法实现呢?of course!
装饰器就能在不改动被装饰对象的源代码以及调用方式的前提下,为被装饰对象添加新功能的一种手段!
3、如何用装饰器
即闭包函数的运用!
我们先来定义个简单的算数函数,并调用得到结果!
def square_sum(a, b):
return 5**a + 3**b
print(square_sum(3, 4))
# 执行得到结果
206
这个函数定义是只有算数功能,并没有打印结果功能,我们需要在不改动它源码的情况下给square_sum添加打印功能!
def square_sum(a, b):
return 5**a + 3**b
def decorator(func):
def print_str(a, b):
print('输入值为:', a, b)
print('计算结果为:', func(a, b))
return print_str
square_sum = decorator(square_sum)
square_sum(3, 4)
# 执行得到结果
输入值为: 3 4
计算结果为: 206
在上面示例中,没有改动函数square_sum的代码,也没更改它的调用方式;对调用者来说,一切似乎照旧,实际运行结果却不一样了!看山是山,山却不是山!
上面的示例是个很简单的示例,但是每次装饰都得手动定义变量,这很不Python!因此有了个语法来自动完成调用装饰器,出来吧,“@”!
如下所示,只需要在被装饰对象定义之前,用@DECORATOR方式即可完成赋值操作!装饰器定义必须得在@调用之前,牢记Python先定义后使用!
def decorator(func):
def print_str(a, b):
print('输入值为:', a, b)
print('计算结果为:', func(a, b))
return print_str
@decorator
def square_sum(a, b):
return 5**a + 3**b
square_sum(3, 4)
在这个例子中,@decorator相当于
square_sum = decorator(square_sum)
4、有参装饰器
在上面的例子中,装饰器@decorator默认被装饰对象为唯一的函数;但有时候因为某些原因,我们又需要更多的参数,又不能修改原有的参数(比如形参那里写的是*args和**kwargs);这时就需要再多包一层来传递参数了!仅需要在调用装饰器时跟上参数即可!
def de1(sanxi):
def decorator(func):
def print_str(a, b):
print('输入值为:', a, b)
print('计算结果为:', func(a, b))
print('hello,', sanxi)
return print_str
return decorator
@de1('andy')
def square_sum(a, b):
return 5**a + 3**b
square_sum(3, 4)
# 执行得到结果
输入值为: 3 4
计算结果为: 206
hello, andy
5、了解函数对象的属性
函数对象有个属性__name__,它可以显示函数的名称;__doc__显示注释信息!如果我们调用了装饰器,那么装饰器会覆盖被装饰对象的名称!Python提供了一个内置的工具包和装饰器可以实现这个功能!如下所示:
# 调用装饰器时(未调用工具包)
def decorator(func):
def print_str(a, b):
'''
这是装饰器注释
'''
print('输入值为:', a, b)
print('计算结果为:', func(a, b))
return print_str
@decorator
def square_sum(a, b):
'''
这是被装饰对象注释
'''
return 5**a + 3**b
print(‘函数名称:’, square_sum.__name__)
print(‘函数注释:’, square_sum.__doc__)
# 执行得到结果
函数名称: print_str
函数注释:
这是装饰器注释
我们调用工具包来进一步伪装,让装饰器属性变得跟原函数一模一样!
from functools import wraps
def decorator(func):
@wraps(func)
def print_str(a, b):
'''
这是装饰器注释
'''
print('输入值为:', a, b)
print('计算结果为:', func(a, b))
return print_str
@decorator
def square_sum(a, b):
'''
这是被装饰对象注释
'''
return 5**a + 3**b
print('函数名称:', square_sum.__name__)
print('函数注释:', square_sum.__doc__)
# 执行得到结果
函数名称: square_sum
函数注释:
这是被装饰对象注释
6、总结
装饰器核心是“name binding”,即名称绑定关系!在Python项目中得到广泛运用,尤其是在编写程序框架中!必须要学会灵活使用它!