系统学习Python——装饰器:类装饰器-[跟踪对象接口:使用类装饰器跟踪接口]

本文介绍了如何使用类装饰器实现`__getattr__`技术,以追踪Python实例的属性访问。不同于函数装饰器,类装饰器可以跟踪整个对象接口,如Spam和Person类的实例属性获取。装饰器通过创建Wrapper实例并维护状态,展示了其在追踪和状态管理方面的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分类目录:《系统学习Python》总目录


类装饰器为实现这种__getattr__技术提供了一种方便的替代方法,可用来包装一个完整接口。例如,从Python2.6和Python3.0起,前面的类示例可编写为一个类装饰器,能够触发被包装实例的创建,而不是把一个预产生的实例传递到包装器的构造函数中(在这里使用**kargs扩展以支持关键字参数,并且统计了访问的次数来阐明可更改的状态)·

def Tracer(aClass):
    class Wrapper:
        def __init__(self, *args, **kwargs):
            self.fetches = 0
            self.wrapped = aClass(*args, **kwargs)
            
        def __getattr__(self, attrname):
            print('Trace:' + attrname)
            self.fetches += 1
            return  getattr(self.wrapped, attrname)
    return Wrapper

@Tracer
class Person:
    def __init__(self, name, hours, rate):
        self.name = name
        self.hours = hours
        self.rate = rate
        
    def pay(self):
        return self.hours * self.rate
    
@Tracer
class Spam:
    def display(self):
        print('!!!')

这里与我们前面在文章《系统学习Python——装饰器:函数装饰器》中遇到的跟踪器装饰器有很大不同,注意到这点很重要。在那里,我们看到了装饰器使我们能够跟踪和计时对给定函数或方法的调用。相反,通过拦截实例创建调用,这里的类装饰器允许我们跟踪整个对象接口。也就是说,跟踪对实例的任何属性的访问。

下面是这段代码在Python3.X和Python2.6+下产生的输出:SpamPerson类实例的属性获取都会启用Wrapper类中的__getattr__逻辑,由于foodbob确实都是Wrapper的实例,而且装饰器对实例创建调用也进行了重定向。

输入:

a = Spam()
a.display()
print([a.fetches])

输出:

Trace:display
!!!
[1]

输入:

bob = Person('Bob', 40, 10)
print(bob.name, bob.pay())

sue = Person('Sue', 50, 15)
print(sue.name, sue.pay())

print([bob.fetches, sue.fetches])

输出:


Trace:name
Trace:pay
Bob 400
Trace:name
Trace:pay
Sue 750
[2, 2]

注意Wrapper类是如何根据每次的装饰保持状态的,并由Tracer函数中嵌套的class语句生成的。还要注意每个实例是如何通过生成一个新的Wrapper实例而有了自己的访问计数器。后面的文章我们将看到,精心编排这一切比你预料中的要难以应付得多。

参考文献:
[1] Mark Lutz. Python学习手册[M]. 机械工业出版社, 2018.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

von Neumann

您的赞赏是我创作最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值