美文网首页
py_27 类装饰器

py_27 类装饰器

作者: 阿登20 | 来源:发表于2020-08-22 16:31 被阅读0次
image.png
1. `@类名`要作为装饰器,需要重写`__call__`方法。实例()实际就是调用的`__call__方法`把call当成wrapper来看。
2. 在类里面为三大方法设计装饰器,只需在类里面设置一个普通函数的模版即可,放在三者上面。
`切记@classmethod @staticmethod必须放在@装饰器上面`
3. 类里面的三大方法作为装饰器,给外部的函数用。先在类里面声明好,
通过@实例.三大方法,静态方法和类方法还可以@类名.方法名。
4. 函数作为类的装饰器,将类名作为参数参进去,返回是一个可调用对象即可,
也可以返回类名本身,从而可以为类增加属性,修改属性值等操作。
5. 外部函数作为装饰器给类的三大方法用。只需要将装饰器函数模版,放在声明类的上方。

类装饰器

实例() 其实是调用__call__方法

因此可以 重写__call__方法,从而给函数添加装饰器

class Test(object):
    def __call__(self, *args, **kwargs):
        print("实例化加括号会调用__call__方法")

t = Test() # t = Test()
t()  # 实例化加括号调用的是__call__ 方法

结果:
实例化加括号会调用__call__方法

1. 重写__call__作为装饰器

# 案例1 在__call__添加装饰器功能

class Test:

    def __init__(self,func):
        """初始化"""
        print("正在初始化")
        self.func = func  # 是 为了在__call__方便调用func
        pass

    def __call__(self, *args, **kwargs):
        print("为装饰器添加功能")
        res = self.func(*args, **kwargs)
        return res


@Test  # test=Test(test)
def test(x,y):
    """测试两数相加"""
    print(f"{x}+{y} = {x+y}")
    return x+y


res = test(1,3)
print(res)

结果:
正在初始化
为装饰器添加功能
1+3 = 4
4

2.给类里面的self,cls,静态方法 添加装饰器,在类内部使用

@classmethod @staticmethod必须放在装饰器上面,因为执行顺序是从上向下的,否则回报 不可调用的错误。

这尼玛这个坑 踩得杠杠滴!!

# 回忆一下函数装饰器的模版吧
from functools import wraps
def outter(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return wrapper

那么能不能给类里面的方法添加装饰器呢,类里面的方法其实就可以看成一个函数嘛。
从这个出发,仔细想想,给类里面方法添加功能,其实就是给函数增加功能。

class Adeng:
    
    def outter(func):
        @wraps(func)
        def wrapper(cls,*args, **kwargs):
            print("装饰器添加功能1")
            res = func(cls,*args, **kwargs)
            print("装饰器添加功能2")
            return res
        return wrapper

    # def outter(func):
    #     @wraps(func)
    #     def wrapper(*args, **kwargs):
    #         print("装饰器添加方法功能1")
    #         res = func(*args, **kwargs)
    #         print("装饰器添加方法功能2")
    #         return res
    #     return wrapper
    
    # def outter(func):
    #     @wraps(func)
    #     def wrapper(self,*args, **kwargs):
    #         print("装饰器添加方法功能1")
    #         res = func(self,*args, **kwargs)
    #         print("装饰器添加方法功能2")
    #         return res
    #     return wrapper 
    
    # 上面注释的代码,三者效果一样。
    # test=outter(test)
    @outter
    def test_01(self, x, y):
        """测试两数相加"""
        print(f"{x}+{y} = {x + y}")
        return x + y

    @classmethod
    @outter
    def test_02(cls, x, y):
        """测试两数相加"""
        print(f"{x}+{y} = {x + y}")
        return x + y


    @staticmethod
    @outter
    def test_03(x, y):
        """测试两数相加"""
        print(f"{x}+{y} = {x + y}")
        return x + y

a = Adeng()
a.test_01(3,2)
Adeng.test_02(10,20)
Adeng.test_03(20,20)

3.在类里面定义装饰器(self cls staticmethod) 在外部应用

# 案例3:在类定义装饰器(self cls staticmethod) 在外部应用

class Adeng:

    def outter_self(self,func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("类里面实例方法作为装饰器添加功能1")
            res = func(*args, **kwargs)
            print("类里面实例方法作为装饰器添加功能2")
            return res
        return wrapper

    @classmethod
    def outter_cls(cls,func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("类里面类方法作为装饰器添加功能1")
            res = func(*args, **kwargs)
            print("类里面类方法作为装饰器添加功能2")
            return res
        return wrapper

    @staticmethod
    def outter_sta(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print("类里面静态方法作为装饰器添加功能1")
            res = func(*args, **kwargs)
            print("类里面静态方法作为装饰器添加功能2")
            return res

        return wrapper
--------------------------------------------------------
a = Adeng() # 实例化

@a.outter_self
def test( x, y):
        """测试两数相加"""
        print(f"{x}+{y} = {x + y}")
        return x + y

@Adeng.outter_cls
def mult( x, y):
    """测试两数相乘"""
    print(f"{x}*{y} = {x*y}")
    return x * y

@Adeng.outter_sta
def mm(x,y):
    print(f"x---{x}\ny---{y}")

test(5,5)
mult(5,5)
mm(5,5)

4. 给类添加属性和方法

def class_decorate(obj):
    print('我是类的装饰器!,00000000000000000')
    obj.age = 22222222222 # 添加类属性

    def fun1(*args, **kwargs):
        print(args, kwargs)
        # return '这是类的装饰器添加的方法,22222222222222'
        return args # 元组包含对象

    obj.fun1 = fun1
    return obj

@class_decorate  # Person = class_decorate(Person)  会先调用Person类里面的方法
class Person:
    def __init__(self, name):
        self.name = name
"""
在类的装饰器中给类添加属性和方法,这里需注意的是,在装饰器中添加方法时,应传入不定长参数,
如果使用对象调用该方法时会自动传入self,加上有时需要自定义参数,所以需要使用不定长参数接收。
我们可以使用__dic__打印该类查看该类的属性和方法

"""

print(Person.__dict__) # 查看该类的属性和方法
for k,v in Person.__dict__.items():
    print(f"{k}:{v};")

"""
__module__:__main__;
__init__:<function Person.__init__ at 0x0000000002965510>;
__dict__:<attribute '__dict__' of 'Person' objects>;
__weakref__:<attribute '__weakref__' of 'Person' objects>;
__doc__:None;
age:22222222222;
fun1:<function class_decorate.<locals>.fun1 at 0x0000000002965488>;
"""

# print(dir(Person)) # 查看对象所有属性和方法

print(Person.age)  # 22222222222
res = Person("阿登").fun1(1,2,3,x=2,y=3) 
print(res) # (<__main__.Person object at 0x00000000028A3518>, 1, 2, 3)

5. 给类添加 类属性

"""
给每个类添加自定义值的属性,此处因参数不固定,所以使用不定长参数kwards接收,
注意这里是要设置属性名,因此使用setattr给类添加属性及其对应值
"""


def outter(**kwargs):
    pass
    def wrapper(obj):
        for k,v in kwargs.items():
            setattr(obj,k,v)
        return obj
    return wrapper

@outter(age=20, sex='男') # @wrapper-->Person=wrapper(Person)
class Person:
    def __init__(self, name):
        self.name = name
    
    def test_01(self):
        print("test_01正在执行")
        pass

print(Person)
print(Person.age) # 20
print(Person.sex) # 男
print(Person.__module__)  # __main__
Person("阿登").test_01() # test_01正在执行

for k,v in Person.__dict__.items():
    print(f"{k}:{v};")
    
for循环结果
__module__:__main__;
__init__:<function Person.__init__ at 0x00000000023759D8>;
test_01:<function Person.test_01 at 0x0000000002375A60>;
__dict__:<attribute '__dict__' of 'Person' objects>;
__weakref__:<attribute '__weakref__' of 'Person' objects>;
__doc__:None;
age:20;
sex:男;

6. 外部函数,给类里面的实例方法和类方法、静态方法加装饰器

  • 装饰器声明时候,在定义类上方
from functools import wraps

def outter(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("添加某个功能")
        res = func(*args, **kwargs)
        return res
    return wrapper

class adeng:

    @outter
    def test_01(self,x,y):
        print("实例方法")
        print(f"{x}--{y}")

    @classmethod
    @outter
    def test_02(cls,x,y):
        print("类方法")
        print(f"{x}--{y}")

    @staticmethod
    @outter
    def test_03():
        print("静态方法")


adeng.test_03()
adeng().test_01(5,6)
adeng.test_02(10,20)
pass

添加某个功能
静态方法

添加某个功能
实例方法
5--6

添加某个功能
类方法
10--20

类装饰器总结:

  1. @类名要作为装饰器,需要重写__call__方法。实例()实际就是调用的__call__方法把call当成wrapper来看。
  2. 在类里面为三大方法设计装饰器,只需在类里面设置一个普通函数的模版即可,放在三者上面。切记@classmethod @staticmethod必须放在@装饰器上面
  3. 类里面的三大方法作为装饰器,给外部的函数用。现在类里面声明好,通过@实例.三大方法,静态方法和类方法还可以@类名.方法名。
  4. 函数作为类的装饰器,将类名作为参数参进去,返回是一个可调用对象即可,也可以返回类名本身,从而可以为类增加属性,修改属性值等操作。
  5. 外部函数作为装饰器给类的三大方法用。只需要将装饰器函数模版,放在声明类的上方。

相关文章

  • py_27 类装饰器

    类装饰器 实例() 其实是调用__call__方法 因此可以 重写__call__方法,从而给函数添加装饰器 1....

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • 装饰器4

    装饰器装饰类 使用类装饰器的时候,记得要返回被装饰的类调用的结果装饰器函数 再 init 之前执行 例子1:给类添...

  • TS装饰器初体验,用装饰器管理koa接口

    typescript中的装饰器有很多种,比如类装饰器、方法装饰器、属性装饰器等等,先看看装饰器的定义吧,下面以类装...

  • decorator

    装饰器 装饰类对象@testclass A{}function test(target){//类对象装饰器函数ta...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • Python | 装饰器

    使用场景 装饰器 ' @ ' 使用 带参数装饰器 装饰器类

  • python 装饰器(类装饰器和函数装饰器)

    一、函数装饰器示例 二、类装饰器

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

网友评论

      本文标题:py_27 类装饰器

      本文链接:https://www.haomeiwen.com/subject/qivvjktx.html