I think you can remove even more templates by writing your own descriptor class that will decorate the loader method. The idea is for the descriptor itself to encode the lazy loading logic, which means that the only thing you define in the real method is the loader itself (this is the only thing that apparently should really change for different values). Here is an example:
class LazyDesc(object): def __init__(self, func): self.loader = func self.secretAttr = '_' + func.__name__ def __get__(self, obj, cls): try: return getattr(obj, self.secretAttr) except AttributeError: print("Lazily loading", self.secretAttr) self.loader(obj) return getattr(obj, self.secretAttr) class State(object): @LazyDesc def positions(self): self._positions = {'some': 'positions'} @LazyDesc def forces(self): self._forces = {'some': 'forces'}
Then:
>>> x = State() >>> x.forces Lazily loading _forces {'some': 'forces'} >>> x.forces {'some': 'forces'} >>> x.positions Lazily loading _positions {'some': 'positions'} >>> x.positions {'some': 'positions'}
Please note that the lazy loading message was printed only on first access for each attribute. This version also automatically creates a "secret" attribute to store real data by adding an underscore to the method name (i.e., the data for positions stored in _positions . In this example, there is no setter, so you can 't do x.positions = blah ( although you can still change positions using x.positions['key'] = val ), but this approach can be extended to customize.
The best part about this approach is that your lazy logic is transparently encoded in the __get__ descriptor, which means that it easily generalizes to other types of templates that you might want to distract in this way.
source share