<p>你误解了描述符是如何在类中找到的。Python将在类层次结构中使用第一个这样的名称。一旦找到,搜索就会停止。<code>B.dd_1</code>存在,因此不考虑<code>A.dd_1</code>。你知道吗</p>
<p>文档告诉您关于<code>B</code>没有定义<code>dd_1</code>的基类;在这种情况下,搜索<code>B</code>,然后搜索<code>A</code>。但是当<code>B</code>具有属性<code>dd_1</code>时,任何进一步的搜索都将停止。你知道吗</p>
<p>注意,搜索顺序是由类MRO(方法解析顺序)设置的。不应区分类<code>__dict__</code>中的搜索和基类的<code>__dict__</code>属性,而应将搜索视为:</p>
<pre><code>def find_class_attribute(cls, name):
for c in cls.__mro__:
if name in c.__dict__:
return c.__dict__[name]
</code></pre>
<p>MRO(由<a href="https://docs.python.org/3/reference/datamodel.html" rel="nofollow noreferrer">^{<cd11>} attribute</a>体现)包括当前类对象:</p>
<pre><code>>>> B.__mro__()
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
</code></pre>
<p>相关文档位于<a href="https://docs.python.org/3/reference/datamodel.html" rel="nofollow noreferrer">datamodel reference</a>;其中<em>自定义类</em>说明:</p>
<blockquote>
<p>Class attribute references are translated to lookups in this dictionary, e.g., <code>C.x</code> is translated to <code>C.__dict__["x"]</code> (although there are a number of hooks which allow for other means of locating attributes). <strong>When the attribute name is not found there, the attribute search continues in the base classes.</strong></p>
</blockquote>
<p>实例属性的实际实现如下:</p>
<ul>
<li>类位于(<code>type(instance)</code>)</li>
<li>类<code>__getattribute__</code>方法被调用(<code>type(instance).__getattribute__(instance, name)</code>)</li>
<li><code>__getattribute__</code>扫描MRO以查看类及其基类上是否存在名称(<code>find_class_attribute(self, name)</code>)
<ul>
<li>如果存在这样一个对象,并且它是一个数据描述符(具有<code>__set__</code>或<code>__delete__</code>方法),则使用该对象,搜索停止。你知道吗</li>
<li>如果有这样一个对象,但它不是数据描述符,则会保留一个引用供以后使用。你知道吗</li>
</ul></li>
<li><code>__getattribute__</code>在<code>instance.__dict__</code>中查找名称
<ul>
<li>如果有这样的物体,搜索就会停止。使用实例属性。你知道吗</li>
</ul></li>
<li>找不到数据描述符,实例dict中也没有属性。但是通过MRO的搜索可能找到了一个非数据描述符对象
<ul>
<li>如果在MRO中找到了一个对象的引用,则使用它并停止搜索。你知道吗</li>
</ul></li>
<li>如果类(或基类)上定义了<code>__getattr__</code>方法,则调用该方法并使用结果。搜索停止。你知道吗</li>
<li>引发<code>AttributeError</code>。你知道吗</li>
</ul>