On Thu, Apr 17, 2003 at 11:53:01AM -0400, Guido van Rossum wrote:
Anyway, if anyone has straightforward ideas about how CALL_ATTR should deal with newstyle classes (if at all), please inform me (preferably via SF) or just grab the patch and run with it. I'm still confused about descrgets and where they come from.
Yes, please. Here's a quick explanation of descriptors:
[ the descriptor describes descriptors ]
Hope this helps!
Well, yes, in that it reminded me to stop looking for how functions get turned into methods. That part is the same for old-style classes, though, and not quite what I'm confused about. What the call_attr patch does is shortcut the instance_getattr functions in a new function, to do just that what is necessary (and no more.) _Py_instance_getmethod() returns NULL for anything that isn't a method, too, letting the slow case handle it. When it does find a would-be method, it returns the unwrapped function. The call_attr function basically does a PyInstance_Check() and a _Py_instance_getmethod(), and calls the returned function.
The problem I have with newstyle classes is where to shortcut what. I understand now how to detect a would-be method, but I'm not sure how to get unwrapped attributes. As far as I understand, types can provide their own getattr function with complete control over descriptors, so there isn't much to shortcut. Unless I should make the shortcut depend on the actual value of tp_getattro, as in shortcut only if it actually is PyObject_GenericGetAttr ? In that case, I'm somewhat sceptical about the speed benefit's cost in maintenance, as it would require a near copy of PyObject_GenericGetAttr (which is already a near-copy of a few other functions :) It's also very hard to control any nested getattrs (possible, I think, because the process goes over all bases' dicts and the instance dict.) Or can we reduce the number of steps PyObject_GenericGetAttr goes through if we know we are just looking for a method ? I don't believe so, but I'm not sure.
(Looking at PyObject_GenericGetAttr with that in mind, I wonder if there isn't a possible crash there. In the first MRO lookup, looking for descr's, if a non-data-descr is found, it is kept around but not INCREF'd until later, after the instance-dict is searched. Am I wrong in believing the PyDict_GetItem of the instance dict can call Python code ? There isn't even as much as an assert(PyDict_Check(dict)) there.)