Lazy evaluation is a useful pattern that can improve your code's efficiency in many situations. One example of this is instance attributes that take long to compute. In this case, the list of relatives is only computed the first time Person#relatives is accessed. After that, it is stored in Person#_relatives to prevent repeated evaluations.
The other gist uses decorators to define a @lazy_property decorator that does the same thing. This reduces the amount of boilerplate in a class, especially if it uses alot of lazy properties. From http://stevenloria.com/lazy-evaluated-properties-in-python/
# Better
class Person:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
self._relatives = []
@property
def relatives(self):
if not self._relatives:
self._relatives = ... # Get all relatives
return self._relatives
# Even better
def lazy_property(fn):
'''Decorator that makes a property lazy-evaluated.
'''
attr_name = '_lazy_' + fn.__name__
@property
def _lazy_property(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, fn(self))
return getattr(self, attr_name)
return _lazy_property
class Person:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
@lazy_property
def relatives(self):
# Get all relatives
relatives = ...
return relatives