Skip to content

Instantly share code, notes, and snippets.

@suminb
Last active August 29, 2015 14:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suminb/55cfdadaf4fa31c85518 to your computer and use it in GitHub Desktop.
Save suminb/55cfdadaf4fa31c85518 to your computer and use it in GitHub Desktop.
class retraceable_property(property):
"""A decorator that traces how a property changes over time.
In real life, you may find yourself in a situation in which you keep track
of a variable that changes over time. It may be a path of a moving object
or (something else; it's late at night and my brain is a bit cloudy so I
can't give you another brilliant example. I'll fill this in later). As an
over-simplified example, you may write code to keep adding two to a
variable in every
second as follows:
v = 1
for _ in range(10):
v += 2
time.sleep(1)
This is a very straightforward solution but it unneccessarily consumes
system resources. In many cases, the value of variable may be represented
as a function of time. For the particular case presented above, it would
be as following:
def f(x, t): x + t * 2
This can be further generalized.
class Foo(object):
@retraceable_property(self.f):
def bar(self, x, t):
return x + t * 2
foo = Foo()
foo.bar = 1
time.sleep(10)
print(foo.bar)
The value of a property can be deduced at any moment without having to
actually perform intermediate steps.
"""
last_accessed = None
def __init__(self, func, name=None, doc=None, time_delta_threshold=0.1):
self.__name__ = name or func.__name__
self.__module = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
self.time_delta_threshold = time_delta_threshold
def __set__(self, obj, value):
self.obj = obj
self.value = value
def __get__(self, obj, type=None):
"""If the time delta is less than the threshold returns the current
value. Otherwise, returns a newly calculated value by
`self.func()`."""
import time
time_delta = time.time() - self.last_accessed \
if self.last_accessed is not None else 0
self.last_accessed = time.time()
if time_delta < self.time_delta_threshold:
return self.value
else:
self.value = self.func(self.obj, self.value, time_delta)
return self.value
class Foo(object):
@retraceable_property
def bar(self, x, t):
return x + t * 2
def test():
foo = Foo()
foo.bar = 1
print(foo.bar)
import time
time.sleep(2)
print(foo.bar)
if __name__ == '__main__':
test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment