我尝试更彻底地了解描述符和显式属性名称的查找顺序。
我阅读了描述符howto,其状态如下:
调用的细节取决于obj是对象还是类:
...
对于类,机制在type.__getattribute__()中,它转换B.x为B.__dict__['x'].__get__(None, B)
我在__class__ 上进行了测试,因为它是的数据描述符object
In [47]: object.__class__
Out[47]: type
Run Code Online (Sandbox Code Playgroud)
因此,type由于typeclass创建了包括objectclass 在内的所有类,因此它按预期返回。根据“描述符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>
Run Code Online (Sandbox Code Playgroud)
我猜它返回描述符本身,因为在__get__其中包含某种代码,例如:
if instance is None:
return self
Run Code Online (Sandbox Code Playgroud)
因此,我了解从类调用时返回描述符本身的原因。让我感到困惑的是不同的输出
当它说“ B.x成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__。既然object是在type(object).__mro__,这一查就找到了object.__dict__['__class__']。由于object.__dict__['__class__']是一个数据描述符(它有一个__set__),因此它优先于通过 进行搜索object.__mro__。因此,Python 将其视为object实例object而不是类来执行
descr.__get__(object, type(object))
Run Code Online (Sandbox Code Playgroud)
代替
descr.__get__(None, object)
Run Code Online (Sandbox Code Playgroud)
调用__get__返回type(object),即type。
您的手动descr.__get__(None, object)调用将被视为object一个类而不是 的实例object。通过这种方式调用,描述符返回自身。
为了证明__class__这里没有特殊情况,我们可以创建自己的类,它是其自身的实例,就像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)))
Run Code Online (Sandbox Code Playgroud)
输出:
3
<property object at 0x2aff9f04c5e8>
3
Run Code Online (Sandbox Code Playgroud)
就像 一样object.__class__,“对象样式”描述符处理也发生在这里。(另外,如果您想知道,即使您不编写设置器,属性也是数据描述符。)
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |