python装饰器扩展类方法和元类管理实例

1 python装饰器扩展类方法和元类管理实例

在class语句的末尾,类装饰器把类名重绑定的一个可调用对象;

在class语句的末尾,元类把类对象的创建指定到type的子类;

类装饰器可以管理类对象和类实例;

元类比较适合管理类对象,用于管理类实例会比较复杂。

通过类装饰器也可以扩展类方法。

1.1 基于装饰器的扩展

描述

装饰器通过返回装饰类保留原类类型来管理类。

对装饰类添加方法来自动扩展全部被装饰的类。

示例

# obj 类似 self,类的方法第1个入参为self    
>>> def triple(obj):
    return obj.value*3

>>> def joinf(obj,value):
    return value+'装饰器自动扩展'

>>> def MyDecorator(aCls):
    # 添加装饰类的方法
    aCls.triple=triple
    aCls.joinf=joinf
    # 返回装饰类保留最初的类类型
    return aCls

# 通过装饰器自动添加方法 
>>> @MyDecorator
class ClsA():
    def __init__(self,value):
        self.value=value
    def double(self):
        return self.value*2

    
>>> @MyDecorator
class ClsB():
    value=5

>>> ca1=ClsA(6)
>>> ca1.double()
12
>>> ca1.triple()
18
>>> ca1.joinf('ca1')
'ca1元类自动扩展'
>>> cb1=ClsB()
>>> cb1.triple()
15
>>> cb1.joinf('cb1')
'cb1元类自动扩展'

1.2 装饰器和元类管理类实例

类装饰器可以管理类和实例。

元类可以管理类和实例,比较适合管理类,管理实例需比较多的额外代码。

1.2.1 装饰器管理类实例

描述

装饰器管理类实例需要返回包装器,通过getattr()拦截装饰类的实例属性。

示例

>>> def TracerDeco(aCls):
    # 装饰器管理实例需返回包装器
    class Wrapper:
        def __init__(self,*args,**kargs):
            self.wrapped=aCls(*args,**kargs)
        # 通过__getattr__()拦截实例属性 
        def __getattr__(self,attrname):
            print('装饰器getattr:',attrname)
            return getattr(self.wrapped,attrname)
    return Wrapper

>>> @TracerDeco
class Staff:
    def __init__(self,name,days,rate):
        self.name=name
        self.days=days
        self.rate=rate
    def pay(self):
        return self.days*self.rate

    
>>> s1=Staff('梯阅线条',22,3000)
>>> s1.name,s1.pay()
装饰器getattr: name
装饰器getattr: pay
('梯阅线条', 66000)

1.2.2 元类管理类实例

描述

元类管理类实例,需要先用type()创建类对象,再通过包装器管理类实例,拦截客户类的实例属性。

示例

>>> def TracerMeta(classname,supers,classdict):
    # 元类管理实例先用type()创建类对象
    aClass=type(classname,supers,classdict)
    # 再用包装器管理类实例
    class Wrapper:
        def __init__(self,*args,**kargs):
            self.wrapped=aClass(*args,**kargs)
        def __getattr__(self,attrname):
            print('元类getattr:',attrname)
            return getattr(self.wrapped,attrname)
    return Wrapper# 返回包装器

>>> class Staff(metaclass=TracerMeta):
    def __init__(self,name,days,rate):
        self.name=name
        self.days=days
        self.rate=rate
    def pay(self):
        return self.days*self.rate

    
>>> s1=Staff('梯阅线条',22,3000)
>>> s1.name,s1.pay()
元类getattr: name
元类getattr: pay
('梯阅线条', 66000)

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