python类装饰器基础

1 python类装饰器基础

类装饰器是管理类的一种方式,不是包装单个函数或方法,而是用装饰器的额外逻辑,来包装实例的构建和调用,从而实现对主体类的扩展。

主体类被装饰后,通过主体类创建实例对象时,自动调用装饰器返回的包装器函数,而包装器函数内部会自动调用原来的主体类。

1.1 定义类装饰器

用法

def cls_decorator(cls):
    pass
    return aCallable

描述

cls_decorator:装饰器函数;

cls:类入参

aCallable:可调用对象

类装饰器函数接收一个类,并且返回可调用对象,赋值给原类名。

1.2 类装饰器装饰类

用法

@cls_decorator
class AClass:
    pass
ac=AClass(8)

等价于

class AClass:
    pass
AClass=cls_decorator(AClass)
ac=AClass(8)

描述

@cls_decoratro:@类装饰器函数,下一行接class 主体类;

class AClass:定义主体类;

类装饰器用来装饰类。

执行过程:

@cls_decoraotr:python文件被加载时,@cls_decorator自动调用cls_decorator(AClass)装饰器函数,并且将下一行class定义的类对象AClass作为入参,装饰器返回可调用对象,赋值给类变量AClass。

aCallable:可调用对象,可以是原类,或者新类。

AClass:被重新赋值为可调用对象。

AClass(8):相当于调用可调用对象aCallable(8),而aCallable会将相关操作,给到入参接收到的原类AClass进行操作。

最终,装饰器实现了对主体类的扩展,而且不修改主体类的代码逻辑,不改变主体类的调用方式,即可执行装饰器扩展的额外逻辑。

1.3 类装饰器执行

示例

>>> def cls_decorator(cls):
    print('cls=',cls)
    print('clsid=',id(cls))
    print('cls_decorator 被调用返回原类')
    return cls

>>> @cls_decorator
class TestClsDeco:
    print('TestClsDeco 被调用')

# TestClsDeco 先被执行      
TestClsDeco 被调用
# cls_decorator 后被执行
cls= <class '__main__.TestClsDeco'>
clsid= 2624479393088
cls_decorator 被调用返回原类
>>> id(TestClsDeco)
# id 相同, cls 送给 cls_decorator的入参
2624479393088

描述

先执行主体类,再调用类装饰器,并且将主体类传给装饰器。

1.4 装饰器返回原类

用法

def cls_decorator(cls):
    # 添加修改原类cls的行为
    return cls # 返回原类cls

描述

类装饰器函数接收一个原类cls,装饰器内部添加修改原类的行为,并且返回原类,从而实现对原类的定制-装饰。

示例

>>> def cls_decorator(cls):
    print('cls_decorator 被调用返回原类')
    print('原类添加属性 name')
    cls.name='梯阅线条'
    return cls

>>> @cls_decorator
class TestClsDeco:
    print('TestClsDeco 被调用')
    def __init__(self,url):
        self.url=url

        
TestClsDeco 被调用
cls_decorator 被调用返回原类
原类添加属性 name
>>> tcd=TestClsDeco('tyxt.work')
>>> tcd.name
'梯阅线条'
>>> tcd.url
'tyxt.work'

1.5 返回类包装器

用法

def cls_decorator(cls):
    class CLS_Wrapper:
        def __init__(self,*args):
            self.wrapped=cls(*args)
        # 拦截未定义属性的点号运算
        def __getattr__(self,attr):
            # 指向原类属性的点号运算
            return getattr(self.wrapped,attr)
    return CLS_Wrapper

描述

返回的类包装器是一个新类,与原类不同,并且将新类赋值给原类名称。

self.wrapped=cls:将原类赋值给类包装器的实例属性。

__getattr__():拦截类包装器的实例属性的点号运算。getattr可以使用属性管理的其他内置函数,比如__getattribute__(),__setattr__(),__delattr__(),__call__(),__str__()等,对属性进行管理和拦截。

return getattr(self.wrapped,attr):将拦截的点号运算,指向原类示例属性的点号运算。

return CLS_Wrapper:返回新类。

示例

>>> def cls_decorator(cls):
    print('clsid=',id(cls))
    class CLS_Wrapper:
        def __init__(self,*args):
            self.wrapped=cls(*args)
        def __getattr__(self,attr):
            return getattr(self.wrapped,attr)
    print('CLS_Wrapperid=',id(CLS_Wrapper)) 
    return CLS_Wrapper

>>> @cls_decorator
class AClass:
    def __init__(self,name):
        self.name=name

clsid= 2624479396864
CLS_Wrapperid= 2624479365712
# AClass 赋值为新类 CLS_Wrapper , id 相同
>>> id(AClass)
2624479365712
>>> ac=AClass('梯阅线条')
>>> ac.name
'梯阅线条'

你可能感兴趣的:(python,python)