[Python-Dev] Descriptor API
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/)