[Python-Dev] instancemethod_getattro seems to be partially wrong

Guido van Rossum guido at python.org
Tue Nov 18 01:04:20 EST 2003

> 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/)

More information about the Python-Dev mailing list