python装饰器

省流:直接看最后

从简单的例子开始,定义装饰器register,定义一个简单的类method,使用装饰器装饰类

1
2
3
4
5
6
7
8
9
10
11
12
def register(*args, name=None):
def warpper(method_cls):
print('warpper cls')
return method_cls
print(args, name)
return warpper


@register('hello', name='name')
class method:
def __init__(self):
print('__init__ method class')

当import这个文件或者执行这个文件时,相当于执行了:

1
method = register('hello', name='name')(method)

这一步分开来看就是:

1
2
tmp1 = register('hello', name='name')
method = tmp1(method)

tmp1是一个函数,就是register返回的warpper,然后调用tmp1,参数是类名,返回类本身。

这个执行是在定义类时执行的,并不是实例化时执行的。

比如执行上述代码输出:

1
2
('hello',) name
warpper cls

如果装饰器调用时没参数,那就自动传入类名作为参数。比如:

1
2
3
4
5
6
7
8
9
10
11
def register(*args, name=None):
def warpper(method_cls):
print('warpper cls')
return method_cls
print(args, name)
return warpper

@register
class method:
def __init__(self):
print('__init__ method class')

输出就是:

1
(<class '__main__.method'>,) None

注意:这里将类作为register的参数,相当于

1
method = register(method)

这时,再实例化method类,就会导致报错:代码添加

1
method()

输出:

1
2
3
4
5
(<class '__main__.method'>,) None
Traceback (most recent call last):
File "decorators.py", line 15, in <module>
method()
TypeError: warpper() missing 1 required positional argument: 'method_cls'

warpper缺少参数!这说明调用method()时,已经是在调用warpper()了

省流:

进行到这一步,可以总结了:

假设写了一句

1
2
3
@xxx
class abc:
...

实际执行的就是:

1
abc = xxx(abc)

如果你写的是@xxx(balabala),那就是abc = xxx(balabala)(abc)

也就是不管你@后面写什么,都会自动调用并传入参数为下面的类/函数,(也就是自动在xxx后面加括号并传入类/函数作为参数)


python装饰器
https://jcdu.top/2022/10/23/python装饰器/
作者
horizon86
发布于
2022年10月23日
许可协议