类装饰器跟踪整个类(重定向)以及大坑

装饰器的一些基础知识:

函数装饰器

函数装饰器类装饰器

类装饰的大坑有2种:

1.在作用于类方法的时候,被装饰的类实例无法把自身的self , 传递进装饰类中(__call__),除非使用描述符类装饰器

2.无法简单的保持多个实例 (见下面)


下面用过一个装饰器来重定向,这个函数装饰器可以产生多个实例.

之后的一个例子把下面的函数装饰器修改成类装饰器,将出错(大坑)

#装饰器(函数/类)通常用于装饰一个函数或方法
#*描述符装饰器能更好的支持一个类方法的装饰情况
#装饰整个类,用__getattr__ 来拦截一个类的调用次数

def tracer(aClass):
    class Wrapper:                          #内部类
        def __init__(self,*args,**kwargs):
            self.callTimes = 0
            self.wrapper = aClass(*args,**kwargs)   #原类 , 封装在实例的属性中
        def __getattr__(self, item):
            print('__getattr__')
            self.callTimes += 1
            return getattr(self.wrapper,item)
    return Wrapper

@tracer
class Person:               #Person = tracer(Person) = > Person 现在是一个Wrapper类
    def display(self):
        print('display')
p = Person()                #p 是一个Wrapper对象
p.display()
print(p)
#echo
#__getattr__
#display
#<__main__.tracer.<locals>.Wrapper object at 0x003E7D70>


类装饰的一些坑:把上面的装饰器修改一下

#现在把上面的例子修改一下成类装饰器, 这是类装饰器的坑!!
class Tracer:
    def __init__(self,aClass):          #接受一个类对象
        self.aClass = aClass
        self.wrapper = None             #wrapper是在调用__call__之后产生的Person对象
    def __call__(self, *args, **kwargs):
        print('__call__ ,args:',args,kwargs)
        self.wrapper = self.aClass(*args,**kwargs)  #创建一个Person对象
        return self
    def __getattr__(self, item):
        print('__getattr__')
        return getattr(self.wrapper,item)          #getattr 获取Person对象中的属性
@Tracer
class Person:                               #Person = Tracer(Person) , Person此时是一个Tracer对象
    def __init__(self,name='person'):
        self.name = name
    def printname(self):
        print(self.name)
x = Person('x')
y = Person('y')
x.printname()                       #出错了, 打印出来了y
#echo
#__call__ ,args: ('x',) {}
#__call__ ,args: ('y',) {}
#__getattr__
#y

这个是类装饰器的一个坑, 每当调用Person('xx')之后,Tracer会调用__call__,内部的wrapper就会产生一个对象,wrapper

只会保持最后一个对象的引用

如果要产生多个实例用函数装饰器来的更直接


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值