为何需要装饰器
假设你写了一个购物程序,里面有三个函数分别是加入购物车/付款/确认收货,而这三个函数可能都需要
验证用户登陆操作,一种方法是写一个函数然后分别在之前函数块中引用这个验证登陆的函数,另一种就是装饰器:
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
概括的讲,装饰器的作用就是为已经存在的函数或对象添加额外的功能。
初级装饰器
下面是之前的装饰器实现,以函数为参数传入,然后实现功能:
# 这个是装饰器,实现功能是登陆验证
def wrapper(func):
def inner():
print('登录验证')
func()
return inner
@wrapper
def cost():
print('付款')
@wrapper
def join_car():
print('加入购物车')
@wrapper
def confirm():
print('确认收货')
if __name__ == '__main__':
cost()
带参数的装饰器
当你需要传入参数的时候,Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数了。
def wrapper(func):
def inner(*args, **kwargs):
print('登录验证')
func(*args, **kwargs)
return inner
@wrapper
def confirm(num, price):
print('确认收货%d个%d块钱'%(num, price))
if __name__ == '__main__':
confirm(1, 20)
输出结果:
登录验证
确认收货1个20块钱
高级一点的装饰器
装饰器工厂
其实装饰器工厂就是根据参数返回一个装饰器,本质上也只是函数嵌套
def get_celebrator(char):
def print_style(func):
def inner():
print(char*15)
func()
return inner
return print_style
@get_celebrator('=')
@get_celebrator('*')
def my_print():
print("小白联盟")
my_print()
多层装饰
上面一层代码已经用到多层装饰,打印结果为:
===============
***************
小白联盟
加载顺序是从下往上加载,先返回一个被装饰器装饰过的函数,再继续装饰(‘=’)所以先打印======
类装饰器
简单用__call__实现即可:
class Logging(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('logging')
return self.func(*args, **kwargs)
@Logging
def say(something):
print (something)
say('hello python')