在 CPython 中实现的这个 AttributeError 消息在哪里?

问题描述

我认为此 Python 会话中的 AttributeError 消息

>>> class A: pass
... 
>>> A().x
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
AttributeError: 'A' object has no attribute 'x'

cpython 中 these lines 处的函数 _PyObject_GenericGetAttrWithDict 中实现:

    if (!suppress) {
        PyErr_Format(PyExc_AttributeError,"'%.50s' object has no attribute '%U'",tp->tp_name,name);
    }

但是我在此 Python 会话中找不到 AttributeError 消息的位置

>>> class A: __slots__ = ('x',)
... 
>>> A().x
Traceback (most recent call last):
  File "<stdin>",in <module>
AttributeError: x

cpython 中实现。您能否提供指向 GitHub 存储库中确切行的链接

解决方法

here

case T_OBJECT_EX:
    v = *(PyObject **)addr;
    if (v == NULL)
        PyErr_SetString(PyExc_AttributeError,l->name);
    Py_XINCREF(v);
    break;

这是 PyMember_GetOne 的摘录,这是实现槽描述符的 __get__ 方法的大部分逻辑的地方。

您可能还对描述符如何到达那里感兴趣。 type.__new__ 在内部 translates __slots__ 到一个 PyMemberDef 结构数组,这是用 C 编写的类的一种机制,用于定义对其内部数据的访问。以这种方式生成的所有 PyMemberDef 结构都标记为 T_OBJECT_EX,这意味着它们对应于实例内存布局中的 PyObject *,如果指针为空,则访问应引发 AttributeError。 PyType_Ready 然后 generates 基于 PyMemberDef 数组的槽描述符。