装饰器本质上一个Python函数,它可以让其他函数在不需要做任何代码变动觉得前提下增加额外的功能,
装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事物处理、
缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能
本身无关的雷同代码并继续重用。概况的讲,装饰器的作用就是为已经存在的对象添加额外的功能
# ###################简单的装饰器#########################
def print_fun(fun):
def wrapper():
print('注解')
fun()
return wrapper
'''
函数:print_fun就是装饰器,它把执行真正的业务方法func包裹在函数里面,
看起来像是func被print_func装饰了。在这个例子中,函数进入和退出时,被称为
横切面,这种编程方式被称为面向切面编程
@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作
'''
@print_fun
def func():
print('hello world')
func()
# ###################带返回值的装饰器#########################
def print_fun(fun):
def wrapper():
print('注解')
return fun()
return wrapper
@print_fun
def func():
return 'hello world'
print(func())
# ###################对待参数的函数装饰#########################
def print_fun(fun):
def wrapper(*args, **kwargs):
print('注解')
return fun(*args, **kwargs)
return wrapper
# 业务函数带有参数的情况
@print_fun
def func(x, y):
num_sum = x + y
return num_sum
print(func(1, 2))
# 对参数数量不确定的函数进行装饰
@print_fun
def func2(*x):
return x
print(func2(1, 2))
@print_fun
def func3(**x):
return x
print(func3(x=2))
# ###################带有参数的装饰器#########################
'''
装饰器还有更大的灵活性,例如带有参数的装饰器,装饰器的语法允许我们在
调用时,提供其他参数,比如@decorator(a),这样,就为装饰器的编写使用提供了更大的灵活性
'''
# 装饰器带有参数的情况
def deco(order):
def print_fun(fun):
def wrapper(*args, **kwargs):
if order == '2':
print('fuck')
else:
print('pm xxxx')
return fun(*args, **kwargs)
return wrapper
return print_fun
@deco('1')
def func(x):
return x
print(func(1))
# 装饰器带有不确定参数的情况
def deco(*args, **kwargs):
def print_fun(fun):
def wrapper(*a, **k):
print(args, kwargs)
return fun(*a, **k)
return wrapper
return print_fun
@deco(1, name='kevin')
def func(x):
return x
print(func(1))
# ###################类装饰器#########################
'''
相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器
还可以依靠类的__call__方法,当使用@形式将装饰器附加到函数上时,就会调用此方法
'''
class Fuck:
def __call__(self):
print('fuck pm')
t = Fuck()
t()
'''
像__call__这样前后都带下划线的方法在Python中被称为内置方法,有时候也被称为魔法方法。
重载这些魔法方法一般会改变对象内部行为。
'''
'''
装饰器接受一个callable对象,并返回一个callable对象,用类来实现也是可以的,让类的构造函数
__init__()接受一个函数,然后重载__call(),并返回一个函数,也可以达到装饰器函数的效果
'''
class Demo(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('sx')
return self.func(*args, **kwargs)
@Demo
def func1(x):
return x
print(func1('pm'))
# 带有参数的类装饰器
class Demo(object):
def __init__(self, value='超级'):
self.value = value
def __call__(self, func):
def wrapper(*args, **kwargs):
print(self.value + 'sx')
return func(*args, **kwargs)
return wrapper
@Demo(value='超级')
def fuck_pm(name):
return name
print(fuck_pm('pm'))
# 不能装饰@staticmethod 或者 @classmethod
'''
decorator.py
是一个非常简单的装饰器加强包。你可以很直观的先定义包装函数wrapper(),再使用decorate(func, wrapper)
方法就可以完成一个装饰器。
'''