Descriptors and side effects

Rich Harkins rich at worldsinfinite.com
Mon Nov 5 09:25:06 EST 2007


mrkafk at gmail.com wrote:
> Hello everyone,
> 
> I'm trying to do seemingly trivial thing with descriptors: have
> another attribute updated on dot access in object defined using
> descriptors.

[snip]

> A setter function should have updated self.l just like it updated
> self.s:
> 
> 	def __set__(self, obj, val):
> 		self.s=val
> 		self.l=len(val)
> 		print "setting value:", self.s, "length:", self.l
> 
> Yet it didn't happen.
> 
[snip]

I noticed that Python will block all attribute overrides (either via
__dict__ through setattr) if the property has a __set__ method.  The
standard property has this method and there is no way that I can find to
defeat it.  So, here is what I use:

class ConstProperty(object):
    """
    Provides a property that keeps its return value.  The function will
    only be called on the first access.  After that the same value can
    be used over and over again with no function call penalty.  If the
    cached value needs to be cleared, simply del the attribute.

    >>> class MyClass(object):
    ...     def __init__(self, x):
    ...         self.x = x
    ...     @ConstProperty
    ...     def y(self):
    ...         print "HERE"
    ...         return self.x ** 2
    ...
    >>> obj = MyClass(5)
    >>> obj.y
    HERE
    25
    >>> obj.y
    25
    """

    def __init__(self, fn):
        self.fn = fn

    def __get__(self, target, cls=None):
        if target is None:
            return self.fn		# Helps pydoc
        else:
            obj = self.fn(target)
            setattr(target, self.fn.__name__, obj)
            return obj

This is a little different than what you originally posted, but
hopefully it is close enough to be helpful.

Cheers!
Rich




More information about the Python-list mailing list