
instancemethod_getattro
does this:
if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) { if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) return NULL; } descr = _PyType_Lookup(tp, name); }
f = NULL; if (descr != NULL) { f = TP_DESCR_GET(descr->ob_type); if (f != NULL && PyDescr_IsData(descr)) return f(descr, obj, (PyObject *)obj->ob_type); }
[...] why does it ask for PyDescr_IsData ???
It's the general pattern: a data descriptor on the class can override an attribute on the instance, but a method descriptor cannot. You'll find this in PyObject_Generic{Get,Set}Attr() too, and in type_getattro(). This is so that if you define a method in a class, you can override it by setting an instance variable of the same name; this was always possible for classic classes and I don't see why it shouldn't work for new-style classes. But it should also be possible to put a descriptor on the class that takes complete control. The case you quote is about delegating bound method attributes to function attributes, but the same reasoning applies generally, I would think: unless the descriptor is a data descriptor, the function attribute should have precedence, IOW a function attribute should be able to override a method on a bound instance. Here's an example of the difference: class C: def f(s): pass f.__repr__ = lambda: "42" print C().f.__repr__() This prints "42". If you comment out the PyDescr_IsData() call, it will print "<bound method C.f of <__main__.C instance at 0x...>>". I'm not entirely clear what goes wrong in your case. --Guido van Rossum (home page: http://www.python.org/~guido/)