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