为啥不在实例属性查找中搜索元类的属性?

Posted

技术标签:

【中文标题】为啥不在实例属性查找中搜索元类的属性?【英文标题】:Why aren't metaclass's attributes searched in instance attribute lookups?为什么不在实例属性查找中搜索元类的属性? 【发布时间】:2016-12-01 16:59:27 【问题描述】:

根据 Python 2.7.12 文档,3.4.2.3。调用描述符¶:

属性访问的默认行为是获取、设置或删除 对象字典中的属性。例如,a.x 有一个 以a.__dict__['x'] 开头的查找链,然后 type(a).__dict__['x'],并继续通过基类 type(a) 不包括元类

但是为什么排除元类呢?

如果你不断地调用type(self),不管self是一个实例对象还是类型对象,你最终都会得到<type 'type'>。所以我不明白为什么元类享有这种“特权”。


顺便说一句,我对这个引用有点困惑:例如对象,使用object.__getattribute__,所以我认为查找链应该是这样的:

a.__dict__['x'] type(a).__dict__['x'] b.__dict__[x]btype(a).__mro__ type(b).__dict__[x]btype(a).__mro__ c.__dict__[x]ctype(b).__mro__ ......

我说的对吗?

【问题讨论】:

我看到你正在试验元类和属性访问——你有什么理由不使用 Python 3?今天几乎所有项目都可以使用 Python 3,并且有很多特性/更改没有进入 Python2 @jsbueno 嗯...为了兼容性,我猜。我的大学(实际上是我的同学,我们正在一起做一个项目。)建议我先学习Python2,因为很多模块还没有支持Python3,而且他们可能在不久的将来不支持它。我的实验是为了更好地理解 Python 在后台是如何工作的,如果有一天我决定改用 Python3,它们会很有帮助,对吧? 我认为“许多模块还没有 Python 3 支持”从 2015 年开始就不正确了。现在最重要的事情在 Python3 中确实有效,最重要的是,对于您正在寻求的深入理解,我会说 Python3 更相关。 Python 的 s2 end of line 计划在 2020 年。如果你今天开始一个项目,那就是 3 年之前必须迁移它 - 我不会说它值得。 @jsbueno 好吧,也许我们真的应该使用 Python 3,因为它是未来。 【参考方案1】:

这是因为属性查找搜索type(a)(type(a).__mro__) 的所有碱基,而不是type(a)(type(type(a))) 的所有类型

另外,type(self) 不是连续调用的,所以查找链如下所示:

a.__dict__['x'] type(a).__dict__['x'] b.__dict__[x] for b in type(a).__mro__ raise AttributeError

正如@jsbueno 在评论中明智地指出的那样,第二步实际上包含在第三步中。这是因为对于任何类,假设类CC 本身正是C.__mro__ 中的第一项。

【讨论】:

其实第二步是包含在第三步中的——要了解会发生什么,type(a).__dict__['x']验证包含在b.__dict__[x] for b in type(a).__mro__ @jsbueno 是的,你是对的。类C 本身正是C.__mro__ 中的第一项。答案已编辑。

以上是关于为啥不在实例属性查找中搜索元类的属性?的主要内容,如果未能解决你的问题,请参考以下文章

为啥一个类具有它的元类的属性?

学习日记0827异常处理 元类 自定义元类 自定义元类来实例化类 属性查找顺序

为啥向元类属性闭包组合添加第二个属性会更改第一个属性?

3.1.18 元类的练习

如何向元类实例添加属性?

元类(metaclass)