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)

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

posted @ 2022-10-23 13:57  王冰冰  阅读(53)  评论(0编辑  收藏  举报