You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.7 KiB
Python

from __future__ import division, print_function
from functools import update_wrapper, wraps
import json
import operator
import os
class HashableDict(dict):
def __hash__(self):
return hash(tuple(sorted(self.items())))
def json_memoize(filename):
"""A decorator that memoizes function calls in a JSON file."""
class JsonMemoize:
def __init__(self, fn):
self.fn = fn
update_wrapper(self, fn)
if not os.path.exists(filename):
with open(filename, "w") as f:
json.dump({}, f)
def __call__(self, *args, **kwargs):
with open(filename, "r") as f:
memo = json.load(f)
json_key = repr((self.fn.__name__, args, HashableDict(kwargs)))
if json_key not in memo:
memo[json_key] = self.fn(*args, **kwargs)
with open(filename, "w") as f:
json.dump(memo, f,
indent=4,
separators=(',', ': '),
sort_keys=True)
f.write("\n")
return memo[json_key]
return JsonMemoize
def timed(f):
"""Return a timed version of function f.
The returned function returns a tuple of (time, real return value)
:param f: function to time
"""
@wraps(f)
def wrapper(*args, **kwargs):
import time
time_start = time.time()
return_ = f(*args, **kwargs)
time_end = time.time()
time_delta = time_end - time_start
return time_delta, return_
return wrapper
@json_memoize('json_memoize_tmp.json')
def is_prime(n):
"""Really inefficiently check if n is a prime number."""
if n == 0 or n == 1:
return False
for i in xrange(2, n):
if n % i == 0:
return False
return True
@json_memoize('json_memoize_tmp.json')
def multiply(*args):
"""Multiply all args."""
return reduce(operator.mul, args, 1)
@json_memoize('json_memoize_tmp.json')
def some_with_kwargs(one, two, **kwargs):
"""Add 'one' and 'two' and all the values of the keyword arguments."""
return one + two + reduce(operator.add, [kwargs[k] for k in kwargs], 0)
assert(is_prime(0) is False)
assert(is_prime(1) is False)
assert(is_prime(2) is True)
assert(is_prime(2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10) is False)
is_prime_timed = timed(is_prime)
for c in range(1, 11):
time, result = is_prime_timed(86028157)
assert (result is True)
print("Call {}: {:.2f}s".format(c, time))
assert(multiply(1, 2, 3, 4) == 24)
assert(multiply(1, 2, 3, 4, 5) == 120)
assert(some_with_kwargs(1, 2, three=3, four=4) == 10)