TLDR:屬性查找從調用__getattribute__
開始,它執行鏈接中提到的所有工作。根據對象的類型調用object.__getattribute__
或type.__getattribute__
。
任何屬性查找都會在內部產生LOAD_ATTR
字節碼。
>>> import dis
>>> dis.dis(lambda: foo.x)
1 0 LOAD_GLOBAL 0 (foo)
2 LOAD_ATTR 1 (x)
4 RETURN_VALUE
LOAD_ATTR
然後調用PyObject_GetAttr
。
PyObject_GetAttr
現在尋找對象類型的tp_getattro
或tp_getattr
(deprecated)插槽。現在
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
...
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return NULL;
return (*tp->tp_getattr)(v, (char *)name_str);
}
...
}
如果一個對象都有自己的執行__getattribute__
,然後將其用在其他它退到要麼object.__getattribute__
或type.__getattribute__
基於類型。 tp_getattro
slot如果是object
指向PyObject_GenericGetAttr
並且對於type
指向type_getattro
。
PyObject_GenericGetAttr
and type_getattro
基本上做檢查描述符,字典,插槽等(基於類型)的所有工作,並嘗試返回一個值。如果他們甚至在所有事情之後都找不到它,則會引發AttributeError
,如果對象的類型定義爲__getattr__
,那麼它將被調用。
有了你一直在問的所有這些屬性查詢問題,我想你最終都會想聽到這部分內容。 – user2357112
[相關](https://stackoverflow.com/questions/39043912/python-3-getattribute-vs-dot-access-behaviour),雖然重點是不同的細節比你看到的。 – user2357112