chrise
chrise

Reputation: 4253

python call set property when property missing

I have an object that has several properties containing values that take a while to query. so I dont want to get all the values for those properties when I create the instance, but just when the code path actually requires the property as only a few are needed depending on the code path. The order when I reach certain points int eh code is also not very deterministic, so I cant set the property at a fixed point in the script. So I was going to create a method

def getValue(self, attributeName):
    if hasattr(self, attributeName): 
        return getattr(self, attributeName)
    elif attributeName == 'A1':
        v = ... code to get value for A1
        self.A1 = v
        return v
    elif attributeName == 'A2':
        v = ... code to get value for A2
        self.A2 = v
        return v
    ....

But I was wondering if this is actually a good way to deal with this or if there are some smarter ways that would be preferred. Thanks for any comment

Upvotes: 0

Views: 615

Answers (2)

warvariuc
warvariuc

Reputation: 59674

You can use this decorator:

class cached_property(object):
    """Define property caching its value on per instance basis.
    Decorator that converts a method with a single self argument into a
    property cached on the instance.
    """
    def __init__(self, method):
        self.method = method

    def __get__(self, instance, type):
        res = instance.__dict__[self.method.__name__] = self.method(instance)
        return res

Here is an explanation.

Upvotes: 2

Elektito
Elektito

Reputation: 4155

You can use python properties like this:

class Foo:
    def __init__(self):
        # ordinary attributes
        self.B1 = something
        self.B2 = something_else

    @property
    def A1(self):
        try:
            return self._A1
        except AttributeError:
            self._A1 = ....calculate it....
            return self._A1

Then you can:

foo = Foo()
print foo.A1  # attribute calculated when first used
print foo.A1  # this time, the value calculated before is used

Upvotes: 1

Related Questions