[python]装饰器 decorator @yntactic sugar 装饰器的本质
最编程
2024-06-10 15:25:54
...
装饰器本质
python的装饰器本质上是一个语法糖,本质的意义在于将一个函数以参数的形式传入另一个函数,并且返回一个新的函数的过程。 可能有点难理解,但是一个例子你就会懂
# 这是一个非常简单装饰器
def decorator(func):
def inner(*args, **kwargs):
print("run decorator")
return func(*args, **kwargs)
return inner
上面的代码定义了一个简单的装饰器,语法糖的调用方式如下
@decorator
def test():
print("run test")
test()
不使用语法糖调用,代码如下:
def test():
print("run test")
test = decorator(test) # 将函数test传入装饰器,并返回一个新的函数
test() 调用结果和上面一模一样
带参数的装饰器
带参数的装饰器本质是还是和简单的装饰器一样
def decorator_num(num):
def decorator(func):
def inner(*args, **kwargs):
print(num)
return func(*args, **kwargs)
return inner
return decorator
@decorator_num(2) # 注意这里是加了括号,所以会先调用将返回的结果在作为装饰器
def test():
print("test")
test()
上面的调用方法等效于
def test():
print("test")
test = decorator_num(2)(test)
test()
使用装饰器需要注意的地方
- 对于带参数的装饰器是不可以在inner函数中修改参数的值,只能读取,看下面例子
def decorator_num(num):
def decorator(func):
def inner(*args, **kwargs):
num += 1 # 如果我修改num的值,那么会直接报错
print(num)
return func(*args, **kwargs)
return inner
return decorator
@decorator_num(2)
def test():
print("test")
test()
- 对于多个装饰器的执行顺序,包装的时候,从下往上,所以执行的时候,就是从上往下,看下面例子
def decorator_1(func):
def inner(*args, **kwargs):
print("decorator_1")
return func(*args, **kwargs)
return inner
def decorator_2(func):
def inner(*args, **kwargs):
print("decorator_2")
return func(*args, **kwargs)
return inner
@decorator_2
@decorator_1
def test():
print("test")
test()
# 打印结果
# decorator_2
# decorator_1
# test
把上面的调用方式修改一下你就更容易理解了
def test():
print("test")
test = decorator_2(decorator_1(test))
test() # 打印结果与上面一致,因为本质都是一样的
- 由于装饰器会返回一个新的函数,所以原本函数的一些元数据会被更改,这个解决也简单,给所有的inner方法在加一个装饰器即可 如下
from functools import wraps
def decorator_1(func):
@wraps(func)
def inner(*args, **kwargs):
print("decorator_1")
return func(*args, **kwargs)
return inner
类装饰器
类装饰器分为两种,第一种是作用在类上面的装饰器,也就是给类使用的,第二种是装饰器本身就是类。
作用在类上面的装饰器
def decorator(func):
def inner(*args, **kwargs):
print("decorator")
return func(*args, **kwargs)
return inner
@decorator
class A:
pass
A = decorator(A)() # 和上面的写法完全一样
装饰器本身就是类
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('decorator')
return self.func(*args, **kwargs)
@Decorator
def a():
print('a')
a = Decorator(a)() # 和上面的写法完全一样