enthought / enthought/traits

chained cached properties get evaluated too often

Open
#200 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
462
Forks
90
PR merge metrics
No merged PRs in 30d

Description

When a cached property depends on an intermediate cached property, the intermediate property gets immediately evaluated when it's dependencies change. This is suboptimal, as cached properties are typically expensive to compute and therefore should only be computed when needed. In particular, during object construction, when the object is unlikely to be in a valid state anyway, properties are likely to be called several times. Take the following example:

```
class Test(HasTraits):
a = Int
b = Int
c = Property(depends_on='a,b')
d = Property(depends_on='a,c')
e = Property(depends_on='c,d')

@cached_property
def _get_c(self):
print('Test._get_c')
return self.a*self.b

@cached_property
def _get_d(self):
print('Test._get_d')
return self.a*self.c

@cached_property
def _get_e(self):
print('Test._get_e')
return self.c+self.d

t = Test(a=1,b=2)
```

This will print

```
Test._get_c
Test._get_d
Test._get_c
Test._get_d
```

so two calls each, without really needed at all.

The reason is of course the same as in issue #94: The traits notification invalidating the chained property's cache triggers the computation of the `old` value of the intermediate property. However, contrary to the general case, here one could solve this by always traversing the dependency chain to it's end, i.e. in the example above, both `d` and `e` should `depends_on='a,b'` instead. However, it would be nice if traits would do this for us automatically, as in some cases these properties could be on different objects, and encapsulation should not require us to know if these traits on the other object are actually properties or not, or on what traits these depend.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.