[Python-Dev] Descriptor API (original) (raw)

Guido van Rossum guido@python.org
Fri, 23 May 2003 10:06:05 -0400


I was doing some tricks with metaclasses and descriptors in Python 2.2 and stumbled on the following:

>>> class test(object): ... a = property(lambda: 1) ... >>> print test.a <property object at 0x01504D20> >>> print test.a.set <method-wrapper object at 0x01517220> >>> print test.a.fset None What this means in practice, is that if I want to test if a descriptor is read-only I have to have two tests: One for custom descriptors, checking that getting set does not barf and another for property, checking that fset returns None.

Why are you interested in knowing whether a descriptor is read-only?

So, why doesn't getting set raise AttributeError in the above case?

This is a feature. The presence of set (even if it always raises AttributeError when called) signals this as a "data descriptor". The difference between data descriptors and others is that a data descriptor can not be overridden by putting something in the instance dict; a non-data descriptor can be overridden by assignment to an instance attribute, which will store a value in the instance dict.

For example, a method is a non-data descriptor (and the prevailing example of such). This means that the following example works:

class C(object): def meth(self): return 42

x = C() x.meth() # prints 42 x.meth = lambda: 24 x.meth() # prints 24

Is this a bug? If it's not, it sure is a (minor) feature request from my part :-)

Because of the above explanation, the request cannot be granted.

You can test the property's fset attribute however to tell whether a 'set' argument was passed to the constructor.

--Guido van Rossum (home page: http://www.python.org/~guido/)