[Python-Dev] Descriptor API

Gonçalo Rodrigues op73418@mail.telepac.pt
Fri, 23 May 2003 15:34:14 +0100


----- Original Message -----
From: "Guido van Rossum" <guido@python.org>
To: "Gonçalo Rodrigues" <op73418@mail.telepac.pt>
Cc: <python-dev@python.org>
Sent: Friday, May 23, 2003 3:06 PM
Subject: Re: [Python-Dev] Descriptor API


> > 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?
>

Introspection dealing with a metaclass that injected methods in its
instances depending on a descriptor. In other words, having fun with
Python's wacky tricks.

> > 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.
>

Thanks for the reply (and also to P. Eby, btw). I was way off track when I
sent the email, because it did not occured to me that property was a type
implementing __get__ and __set__. With this piece of info connecting the
dots the idea is just plain foolish.

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

With my best regards,
G. Rodrigues