返回介绍

OOP和委托:包装对象

发布于 2024-01-29 22:24:15 字数 1255 浏览 0 评论 0 收藏 0

面向对象程序员时常会谈到所谓的委托(delegation),通常就是指控制器对象内嵌其他对象,而把运算请求传给那些对象。控制器负责管理工作,例如,记录存取等。在Python中,委托通常是以__getattr__钩子方法实现的,因为这个方法会拦截对不存在属性的读取,包装类(有时称为代理类)可以使用__getattr__把任意读取转发给被包装的对象。包装类包有被包装对象的接口,而且自己也可以增加其他运算。

例如,考虑文件trace.py。

回忆第29章,__getattr__会获得属性名称字符串。这个程序代码利用getattr内置函数,以变量名字符串从包裹对象取出属性:getattr(X,N)就像是X.N,只不过N是表达式,可在运行时计算出字符串,而不是变量。事实上,getattr(X,N)类似于X.__dict__[N],但前者也会执行继承搜索,就像X.N,而getattr(X,N)则不会(参考第29章关于__dict__属性的内容)。

你可以使用这个模块包装类的做法,管理任何带有属性的对象的存取:列表、字典甚至是类和实例。在这里,wrapper类只是在每个属性读取时打印跟踪消息,并把属性请求委托给嵌入的wrapped对象。

实际效果就是以包装类内额外的代码来增强被包装的对象的整个接口。我们可以利用这种方式记录方法调用,把方法调用转给其他或定制的逻辑,等等。

第31章会重谈被包装对象和委托操作的概念,作为扩展内置类型的一种方式。如果你对委托设计模式感兴趣,也可以参看第31章和第38章有关函数装饰器的讨论:这是关联性很强的概念,旨在用来增加特定函数或方法调用,而不是对对象的整个接口;还有类装饰器,它充当向一个类的所有实例自动添加诸如基于委托的包装器的一种方式。

注意:版本差异提示:在Python 2.6中,运算符重载方法通过把内置操作导向__getattr__这样的通用属性拦截方法来运行。例如,直接打印一个包装对象,针对__repr__或__str__调用该方法,随后把调用传递给包装对象。在Python 3.0中,这种情况不再会发生:打印不会触发__getattr__,并且使用一个默认的显示。在Python 3.0中,新式类在类中查找运算符重载方法,并且完全忽略常规的实例查找。我们将在第37章再次回顾这一话题。现在,记住如果希望运算符重载方法在Python 3.0中被拦截,我们需要在包装类中重新定义它们(通过手动、通过工具或者通过超类)。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文