[Python-Dev] RFC: readproperty

Guido van Rossum guido at python.org
Wed Sep 28 16:47:26 CEST 2005


On 9/28/05, Jim Fulton <jim at zope.com> wrote:
> Read descriptors (defining only __get__) and data descripttors have
> (defining __get__ and __set__) different semantics. In particular,
> read descriptors are overridden by instance data, while data
> descriptors are not.  A common use of read descriptors is for lazily
> computed data:
>
>    class readproperty(object):
>        "Create a read descriptor from a function"
>
>        def __init__(self, func):
>            self.func = func
>
>        def __get__(self, inst, class_):
>            if inst is None:
>                return self
>
>            return self.func(inst)
>
>    class Spam:
>
>        @readproperty
>        def eggs(self):
>            ... expensive computation of eggs
>
>            self.eggs = result
>            return result
>
> When we ask for the eggs attribute the first time, we call the
> descriptor, which calls the eggs function.  The function sets the eggs
> attribute, overriding the descriptor. The next time the eggs attribute
> is accessed, the saved value will be used without calling the
> descriptor.
>
> I do this often enough that I think it would be useful to include it
> in python, either as a builtin (like property) or in the library.  (Or
> possibly by adding an option to property to generate a read
> descriptor.) I'd be happy to add this for 2.5.
>
> Thoughts?

I like the idea of adding this functionality somewhere. I do note that
the semantics were somewhat of an accident, required by backwards
compatibility with pre-2.2 method lookup semantics.

I think we need to be real careful with chosing a name -- in Jim's
example, *anyone* could assign to Spam().eggs to override the value.
The name "readproperty" is too close to "readonlyproperty", but
read-only it ain't! "Lazy" also doesn't really describe what's going
on.

I believe some folks use a concept of "memo functions" which resemble
this proposal except the notation is different: IIRC a memo function
is always invoked as a function, but stores its result in a private
instance variable, which it returns upon subsequent calls. This is a
common pattern. Jim's proposal differs because the access looks like
an attribute, not a method call. Still, perhaps memoproperty would be
a possible name.

Another way to look at the naming problem is to recognize that the
provided function really computes a default value if the attribute
isn't already set. So perhaps defaultproperty?

(Sorry to turn this into a naming game, which is bound to produce 100s
of competing proposals that are totally unintuitive except to the
proposer. But naming is important.)

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


More information about the Python-Dev mailing list