python - 对象类的描述符 __class__ 的 __get__ 未按预期返回

标签 python python-3.x

我尝试更彻底地理解描述符和显式属性名称查找顺序。
我读了descriptor howto它声明如下:

The details of invocation depend on whether obj is an object or a class:
...
For classes, the machinery is in type.__getattribute__() which transforms B.x into B.__dict__['x'].__get__(None, B)

我在 __class__ 上测试它,因为它是 object 的数据描述符

In [47]: object.__class__
Out[47]: type   

因此,它按预期返回 type,因为 type 类创建了所有类,包括 object 类。基于'descriptor howto',object.__class__ 变成了object.__dict__['__class__'].__get__(None, object).
但是,当我运行它时,输出是描述符本身,而不是 type

In [48]: object.__dict__['__class__'].__get__(None, object)
Out[48]: <attribute '__class__' of 'object' objects>    

我猜它会返回描述符本身,因为在这个 __get__ 内部有一些类似的代码:

if instance is None:
    return self    

所以,我理解了从类调用时返回描述符本身的原因。让我困惑的是不同的输出

当它说“B.x into B.__dict__['x'].__get__(None, B)'时,我希望输出是相同的。它们为什么不同?

最佳答案

描述符操作方法是一种简化。它掩盖了元类之类的东西,以及类是对象的事实。类是对象,它们通过“对象式”“类式”属性查找和描述符处理。 (如果您想独立验证,可以在 type_getattro 中找到实现。)

查找 object.__class__不只是通过 object.__mro__ ;它还会查看 type(object).__mro__ .在 type(object).__mro__ 中找到的描述符使用“对象式”描述符处理,将类视为其元类的实例,而描述符在 object.__mro__ 中找到使用“类风格”描述符处理。

当你查找object.__class__时, Python 搜索 type(object).__mro__ .自 objecttype(object).__mro__ , 此搜索找到 object.__dict__['__class__'] .自 object.__dict__['__class__']是一个数据描述符(它有一个 __set__ ),这优先于通过 object.__mro__ 的搜索.因此,治疗object作为 object 的实例而不是作为一个类,Python 执行

descr.__get__(object, type(object))

代替

descr.__get__(None, object)

__get__调用返回 type(object) ,即 type .

您的手册 descr.__get__(None, object)来电请客object作为类而不是 object 的实例.以这种方式调用,描述符返回自身。


为了证明__class__这里不是特例,我们可以创建我们的 own 类,它是它自己的一个实例,就像 object是:

class DummyMeta(type):
    pass

class SelfMeta(type, metaclass=DummyMeta):
    @property
    def x(self):
        return 3

SelfMeta.__class__ = SelfMeta

print(SelfMeta.x)
print(SelfMeta.__dict__['x'].__get__(None, SelfMeta))
print(SelfMeta.__dict__['x'].__get__(SelfMeta, type(SelfMeta)))

输出:

3
<property object at 0x2aff9f04c5e8>
3

就像 object.__class__ 一样,“对象式”描述符处理也发生在这里。 (此外,如果您想知道,即使您不编写 setter,属性也是数据描述符。)

关于python - 对象类的描述符 __class__ 的 __get__ 未按预期返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55312116/

相关文章:

python - 识别列中没有值

python - 使用 Django 选择上传文件的文件名

python - 如何在同一显示窗口中绘制 3 个子图? Python

python - Selenium 找不到元素

python - 比较两个字典,如果一个字典中存在键/值对,则删除另一个字典中的键/值对

python - matplotlib:将颜色分配给半径

python-3.x - 如何在Scrapy CrawlSpider中找到当前的start_url?

python - AWS EC2 Boto3 中的 "start_instances() only accepts keyword arguments"错误

python - doctest 中的链式异常

python - 根据对角线项对矩阵进行排序