Lazy evaluation postpones an operation until its result is requested. Generators produce one item at a time, while lazy attributes delay expensive data loading until access. section 7.4.2 section 9.4
Use lazy evaluation when preparing all results up front would waste time or memory.
- Create a generator that remembers its current state and computes the next value only when called. section 7.4.2
- Initialize a potentially large attribute as None, then compute and cache it when a property is first accessed. section 9.4.3
- Avoid loading remote profile data for every follower when the interface initially needs only usernames. section 9.4.1
Deferring follower profile data
A User object can store username immediately and leave _profile_data unset. The first access to profile_data runs the expensive server operation; later accesses return the cached value. This creates users without loading their profiles and performs the work only for profiles that are actually requested. section 9.4.1 section 9.4.3
Listing 9.8 Creating a decorator for a lazy attribute
class User:
def __init__(self, username):
self.username = username
self._profile_data = None
print(f"### User {username} created")
@property
def profile_data(self):
if self._profile_data is None:
print("_profile_data is None")
self._profile_data = self._get_profile_data()
else:
print("_profile_data is set")
return self._profile_data
def _get_profile_data(self):
# get the data from the server and load it into memory
print("*** Run the expensive operation")
fetched_data = "Extensive data, including thumbnail,
followers, etc."
return fetched_data
Inspect the property implementation and its output for object creation, first access, and repeated access. section 9.4.3












