返回介绍

__getattr__ 和 __getattribute__ 比较

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

为了概括__getattr__和__getattribute__之间的编码区别,下面的例子使用了这两者来实现3个属性——attr1是一个类属性,attr2是一个实例属性,attr3是一个虚拟的管理属性,当获取时计算它:

运行时,__getattr__版本拦截对attr3的访问,因为它是未定义的。另一方面,__getattribute__版本拦截所有的属性获取,并且必须将那些没有管理的属性访问指向超类获取器以避免循环:

尽管__getattribute__可以捕获比__getattr__更多的属性获取,但是实际上,它们只是一个主题的不同变体——如果属性没有物理地存储,二者具有相同的效果。

管理技术比较

为了概括我们在本章介绍的4种属性管理方法之间的编码区别,让我们快速地来看看使用每种技术的一个更全面的计算属性的示例。如下的版本使用特性来拦截并计算名为square和cube的属性。注意它们的基本值是如何存储到以下划线开头的名称中的,因此,它们不会与特性本身的名称冲突:

要用描述符做到同样的事情,我们用完整的类定义了属性。注意,描述符把基础值存储为实例状态,因此,它们必须再次使用下划线开头,以便不会与描述符的名称冲突(正如我们将在本章最后的示例中见到的,我们可以通过把基础值存储为描述符状态,从而避免必须重新命名):

要使用__getattr__访问拦截来实现同样的结果,我们再次用下划线开头的名称存储基础值,这样对被管理的名称访问是未定义的,并且由此调用我们的方法。我们还需要编写一个__setattrr__来拦截赋值,并且注意避免其潜在的循环:

最后一个选项,使用__getattribute__来编写,类似于前一个版本。由于我们现在捕获了每一个属性,因此必须把基础值获取指向超类以避免循环:

正如你所见到的,每种技术的编码形式都有所不同,但是,所有4种方法在运行的时候都产生同样的结果:

要了解如何比较这些替代方案以及其他编码选项的更多内容,在本章后面“示例:属性验证”节的属性验证示例中,我们会更多地尝试它们的实际应用。在此之前,我们需要先学习和这些工具中的两种相关的一个缺点。

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

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

发布评论

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