当被问到类装饰器,那么是指装饰类的装饰器,还是类本身作为装饰器来用?

装饰器

装饰器:写代码要遵循开放封闭原则,装饰器本质是一个嵌套函数(被套着的函数就是闭包),它可以让被装饰函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
加载顺序自下而上,执行顺序自上而下
@classmethod,@staticmethod,@property,@xxx.setter,@wraps(),@func_name

# 装饰器的第一层函数被称为 外围函数 , 'func_args' 为要处理的函数
def out(func_args):
	# 外围函数的函数体内定义的函数被称为内嵌函数;传入的参数为要处理的func_args函数的参数
	# 这里我们并不知道 func_args 函数需要传入进来的参数是什么,所以目前写传入可变参数是比较合理的
    def inter(*args, **kwargs):
		# 在 内嵌函数 的函数体内调用 func_args 函数,并将可变参数传入
		# 其实这里我们可以处理更多的逻辑;
		# 我们可以选择执行或者不执行,甚至可以func_args 函数的执行结果进行二次处理
         return func_args(*args, **kwargs)
    # 书写完 内嵌函数的业务之后,我们在 外围函数体内返回 内嵌函数
    return inter             
# 需要注意的是,这里是不执行的(因为没有加括号),这是装饰器的定义规则,是必不可少的
# 只有外围函数返回内嵌函数,才可以被之后的代码执行;(因为所有的业务都在内嵌函数中,不返回就无法执行调用)

类装饰器

装饰类的装饰器

def auth(func):
    def inner(*args, **kwargs):
        res = func(*args, **kwargs)
        res.name='zxr'
        return res
    return inner
@ auth # Person = auth(Person)
class Person():
    pass
p = Person() # auth(Person)() --->返回的是inner()--->返回的是res(Person对象)

-特殊语法糖: Person=auth(Person)
        @auth 
        class Person
    -以后再使用 p=Person()  # auth(Person)()--->inner()---->最终返回的还是Person的对象,只是咱们可能加了一些东西

类本身作为装饰器来用

class Auth:
    # 类加()触发__init__
    def __init__(self, func):  # 将func(被装饰的对象)作为参数传入
        self.func = func  # self.func为被装饰的对象

    def __call__(self, *args, **kwargs):
        print('working here')
        res = self.func(*args, **kwargs)  # add(a, b)接受了俩个值
        return res
@Auth # add = Auth(add)
def add(a,b):  # add 是Auth的对象
    return a + b

res = add(4, 5)  # add加括号,会触发Auth的__call__
print(res)
'''
@Auth  # add=Auth(add)---->类()--->__init__(),执行完这个以后,add就是auth类加括号以后的对象,然后就会触发__call__
def add(a, b):
add 是谁? Auth的对象了,后期调用add()--->Auth对象()----->类的对象()--->__call__--->

''' 
	在某个类中多定义一个__call__方法,这样类作为装饰器装饰函数的时候,函数运行就会运行__call__方法中的内容,这就完成了类作为函数装饰器的作用了

from functools import wraps

class animal:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('working here')
        res = self.func(*args, **kwargs)
        return res

@animal  # test = animal(test)
def test(name, kind):
    word = f'{name} belongs to {kind}'
    return word

A = test('cow','mammals')
print(type(test))
print(A)

'''
执行结果:
working here
<class '__main__.animal'>
cow belongs to mammals
'''
类作为一个装饰器,首先使用__init__将函数实例化,但查看type(test)发现test并不是一个函数,实例化func后,使用self.func即可在任意位置调用函数。但是在—__call__中定义方法才能够装饰到函数中,接下来使用return返回函数运行结果
posted @ 2022-12-16 15:42  张张包~  阅读(38)  评论(0编辑  收藏  举报