8000 gh-102213: Optimize the performance of `__getattr__` (GH-102248) · python/cpython@aa0a73d · GitHub
[go: up one dir, main page]

Skip to content

Commit aa0a73d

Browse files
authored
gh-102213: Optimize the performance of __getattr__ (GH-102248)
When __getattr__ is defined, python with try to find an attribute using _PyObject_GenericGetAttrWithDict find nothing is reasonable so we don't need an exception, it will hurt performance.
1 parent 5ffdaf7 commit aa0a73d

File tree

4 files changed

+14
-3
lines changed

4 files changed

+14
-3
lines changed

Include/internal/pycore_object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
370370
extern int _PyObject_IsInstanceDictEmpty(PyObject *);
371371
extern int _PyType_HasSubclasses(PyTypeObject *);
372372
extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
373+
extern PyObject* _PyObject_GenericTryGetAttr(PyObject *, PyObject *);
373374

374375
// Access macro to the members which are floating "behind" the object
375376
static inline PyMemberDef* _PyHeapType_GET_MEMBERS(PyHeapTypeObject *etype) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix performance loss when accessing an object's attributes with ``__getattr__`` defined.

Objects/object.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,12 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
14051405
return _PyObject_GenericGetAttrWithDict(obj, name, NULL, 0);
14061406
}
14071407

1408+
PyObject *
1409+
_PyObject_GenericTryGetAttr(PyObject *obj, PyObject *name)
1410+
{
1411+
return _PyObject_GenericGetAttrWithDict(obj, name, NULL, 1);
1412+
}
1413 8000 +
14081414
int
14091415
_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
14101416
PyObject *value, PyObject *dict)

Objects/typeobject.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8247,14 +8247,17 @@ _Py_slot_tp_getattr_hook(PyObject *self, PyObject *name)
82478247
(Py_IS_TYPE(getattribute, &PyWrapperDescr_Type) &&
82488248
((PyWrapperDescrObject *)getattribute)->d_wrapped ==
82498249
(void *)PyObject_GenericGetAttr))
8250-
res = PyObject_GenericGetAttr(self, name);
8250+
/* finding nothing is reasonable when __getattr__ is defined */
8251+
res = _PyObject_GenericTryGetAttr(self, name);
82518252
else {
82528253
Py_INCREF(getattribute);
82538254
res = call_attribute(self, getattribute, name);
82548255
Py_DECREF(getattribute);
82558256
}
8256-
if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
8257-
PyErr_Clear();
8257+
if (res == NULL) {
8258+
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
8259+
PyErr_Clear();
8260+
}
82588261
res = call_attribute(self, getattr, name);
82598262
}
82608263
Py_DECREF(getattr);

0 commit comments

Comments
 (0)
0