Last active
August 29, 2015 14:18
-
-
Save suminb/55cfdadaf4fa31c85518 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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