问题描述
我认为此 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
数组的槽描述符。