Project Description

Why?

Makes caching of time or computational expensive properties quick and easy.

Because I got tired of copy/pasting this code from non-web project to non-web project.

I needed something really simple that worked in Python 2 and 3.

How to use it

Let’s define a class with an expensive property. Every time you stay there the
price goes up by $50!

classMonopoly(object):def__init__(self):self.boardwalk_price=500@propertydefboardwalk(self):# In reality, this might represent a database call or time# intensive task like calling a third-party API.self.boardwalk_price+=50returnself.boardwalk_price

fromcached_propertyimportcached_propertyclassMonopoly(object):def__init__(self):self.boardwalk_price=500@cached_propertydefboardwalk(self):# Again, this is a silly example. Don't worry about it, this is# just an example for clarity.self.boardwalk_price+=50returnself.boardwalk_price

Working with Threads

What if a whole bunch of people want to stay at Boardwalk all at once? This means using threads, which
unfortunately causes problems with the standard cached_property. In this case, switch to using the
threaded_cached_property:

importthreadingfromcached_propertyimportthreaded_cached_propertyclassMonopoly(object):def__init__(self):self.boardwalk_price=500self.lock=threading.Lock()@threaded_cached_propertydefboardwalk(self):"""threaded_cached_property is really nice for when no one waits
for other people to finish their turn and rudely start rolling
dice and moving their pieces."""sleep(1)# Need to guard this since += isn't atomic.withself.lock:self.boardwalk_price+=50returnself.boardwalk_price

Timing out the cache

Sometimes you want the price of things to reset after a time. Use the ttl
versions of cached_property and threaded_cached_property.

importrandomfromcached_propertyimportcached_property_with_ttlclassMonopoly(object):@cached_property_with_ttl(ttl=5)# cache invalidates after 5 secondsdefdice(self):# I dare the reader to implement a game using this method of 'rolling dice'.returnrandom.randint(2,12)

Now use it:

>>>monopoly=Monopoly()>>>monopoly.dice10>>>monopoly.dice10>>>fromtimeimportsleep>>>sleep(6)# Sleeps long enough to expire the cache>>>monopoly.dice3>>>monopoly.dice3