New submission from Xiang Zhang: Usually when we access an object's __dict__, it will finally reach subtype_dict[0]. When involving builtin base, it may delegates to the base's __dict__ descriptor. In such a case, it is possible for the __dict__ descriptor to initialize the dict object if it's NULL. This is what PyObject_GenericGetDict does. But if the __dict__ descriptor initialize dict to other mapping objects instead of dict object, accessing __dict__ explicitly first or implicitly by attribute setting will result in different behaviours. If we first access obj.__dict__, obj.__dict__ will set to the mapping object, otherwise it will be set to a dict.
Let's make a example. For convenience I alter BaseException's __dict__ descriptor, changing PyObject_GenericGetDict to custom_getdict: PyObject * custom_getdict(PyObject *obj, void *context) { PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj); dict = *dictptr; if (dict == NULL) { *dictptr = dict = PyDict_New(); PyDict_SetItemString(dict, "test", PyDict_New()); } Py_XINCREF(dict); return dict; } And then the use case: >>> BaseException().__dict__ {'test': {}} >>> class A: ... pass ... >>> class B(A, BaseException): ... def __init__(self): ... self.__dict__['a'] = 1 ... self.b = 2 ... >>> class C(A, BaseException): ... def __init__(self): ... self.a = 1 ... self.__dict__['b'] = 2 ... >>> B().__dict__ {'b': 2, 'test': {}, 'a': 1} >>> C().__dict__ {'a': 1, 'b': 2} Since a and b are not descriptors, I think B().__dict__ and C().__dict__ should lead to same result but they are not. I think it's because PyObject_GenericSetAttr doesn't go the same way as subtype_dict so when it finds __dict__ is not initialized it always assign it a new dict. I am not sure this is a bug or a case worth fixing or is designed deliberately. BTW, subtype_dict was introduced in [1]. [0] https://hg.python.org/cpython/file/tip/Objects/typeobject.c#l2069 [1] http://bugs.python.org/issue1303614 ---------- components: Interpreter Core messages: 269470 nosy: rhettinger, serhiy.storchaka, xiang.zhang priority: normal severity: normal status: open title: Possible different behaviour of explicit and implicit __dict__ accessing when involving builtin types' __dict__ descriptors type: behavior versions: Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue27411> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com