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

news/2024/9/21 12:38:08 标签: Python, python, 装饰器, 函数, , 对象, 方法

目录:《系统学习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.


http://www.niftyadmin.cn/n/5393736.html

相关文章

论文精读--GPT3

不像GPT2一样追求zero-shot,而换成了few-shot Abstract Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnos…

如何修改Pytorch scripted_model 模型

如何修改Pytorch scripted_model 模型 源码 本文演示了如何修改Pytorch scripted_model 结构,需求背景 某些AI加速卡的推理软件栈会对模型做图优化,一些模型的图匹配策略不完善,导致编译失败方案一是等待厂家解决,方案二是自己修改图结构,向厂家支持的结构靠拢 源码 import …

外包干了3个月,技术倒退1年。。。

先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近6年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

Redis高并发分布锁实战

Redis高并发分布锁实战 问题场景 场景一: 没有捕获异常 // 仅仅加锁 // 读取 stock15 Boolean ret stringRedisTemplate.opsForValue().setIfAbsent("lock_key", "1"); // jedis.setnx(k,v) // TODO 业务代码 stock-- stringRedisTemplate.delete(&quo…

【蓝桥杯】拓扑排序

一.拓扑排序 1.定义: 设G(V,E)是一个具有n个顶点的有向图,V中的顶点序列称为一个拓扑序列,当且仅当满足下列条件:若从顶点到有一条路径,则在顶点序列中顶点必在之前。 2.基本思想…

Flutter学习5 - Dart 方法类型

1、Dart 方法介绍 方法的构成:返回值 方法名 参数 int sum1(int a, int b) {return a b; }返回值类型可缺省 sum2(int a, int b) {return a b; }参数类型可缺省 sum3(a, b) {return a b; }可通过 { } 设置可选参数;并为可选参数设置默认值 int…

LeetCode 2960.统计已测试设备

给你一个长度为 n 、下标从 0 开始的整数数组 batteryPercentages ,表示 n 个设备的电池百分比。 你的任务是按照顺序测试每个设备 i,执行以下测试操作: 如果 batteryPercentages[i] 大于 0: 增加 已测试设备的计数。 将下标在 …

lua函数定义

1.函数定义\n定义格式如下: optional_function_scope function function_name( argument1, argument2, argument3..., argumentn) function_body return result_params_comma_separated end optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数…