python装饰器
省流:直接看最后
从简单的例子开始,定义装饰器register,定义一个简单的类method,使用装饰器装饰类
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这个文件或者执行这个文件时,相当于执行了:
method = register('hello', name='name')(method)
这一步分开来看就是:
tmp1 = register('hello', name='name')
method = tmp1(method)
tmp1是一个函数,就是register返回的warpper,然后调用tmp1,参数是类名,返回类本身。
这个执行是在定义类时执行的,并不是实例化时执行的。
比如执行上述代码输出:
('hello',) name
warpper cls
如果装饰器调用时没参数,那就自动传入类名作为参数。比如:
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')
输出就是:
(<class '__main__.method'>,) None
注意:这里将类作为register的参数,相当于
method = register(method)
这时,再实例化method类,就会导致报错:代码添加
method()
输出:
(<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()了
省流:
进行到这一步,可以总结了:
假设写了一句
@xxx
class abc:
...
实际执行的就是:
abc = xxx(abc)
如果你写的是@xxx(balabala),那就是abc = xxx(balabala)(abc)