Changeset 581 for branches


Ignore:
Timestamp:
10/17/12 19:17:28 (4 years ago)
Author:
mmckerns
Message:

strong improvements to float caching in memoize, works recursively on iterables

Location:
branches/decorate
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/decorate/memoize.py

    r535 r581  
    22a decorator named 'memoized' that can memoize a *method* on an object. 
    33""" 
     4def isiterable(x): 
     5 #try: 
     6 #    from collections import Iterable 
     7 #    return isinstance(x, Iterable) 
     8 #except ImportError: 
     9  try: 
     10    iter(x) 
     11    return True 
     12  except TypeError: return False 
    413 
    5 def arglist_round(tol=0): 
    6     """Decorator that rounds all floats in args and kwds to given decimal tol. 
    7     """ 
    8     #FIXME: works on foo([1.1111, 2.12345])... and foo(1.1111, 2.12345) 
    9     #       but not recursively into nested lists; also always assumes lists 
    10     @arg_round(tol) 
    11     def rounded_arg(*args): 
    12         return args 
     14def deep_round_factory(tol): 
     15  def deep_round(*args, **kwds): 
     16    argstype = type(args)  
     17    _args = list(args) 
     18    _kwds = kwds.copy() 
     19    for i,j in enumerate(args): 
     20      if isinstance(j, float): _args[i] = round(j, tol) # don't round int 
     21      elif isinstance(j, (str, unicode, type(BaseException()))): continue 
     22      elif isinstance(j, dict): _args[i] = deep_round(**j)[1] 
     23      elif isiterable(j): #XXX: fails on the above, so don't iterate them 
     24        jtype = type(j) 
     25        _args[i] = jtype(deep_round(*j)[0]) 
     26    for i,j in kwds.items(): 
     27      if isinstance(j, float): _kwds[i] = round(j, tol) 
     28      elif isinstance(j, (str, unicode, type(BaseException()))): continue 
     29      elif isinstance(j, dict): _kwds[i] = deep_round(**j)[1] 
     30      elif isiterable(j): #XXX: fails on the above, so don't iterate them 
     31        jtype = type(j) 
     32        _kwds[i] = jtype(deep_round(*j)[0]) 
     33    return argstype(_args), _kwds 
     34  return deep_round 
    1335 
    14     def isiterable(x): 
    15        #try: 
    16        #    from collections import Iterable 
    17        #    return isinstance(x, Iterable) 
    18        #except ImportError: 
    19         try: 
    20             iter(x) 
    21             return True 
    22         except TypeError: return False 
     36""" 
     37>>> deep_round = deep_round_factory(tol=0)  #FIXME: convert to decorator !!! 
     38>>> deep_round([1.12,2,{'x':1.23, 'y':[4.56,5.67]}], x=set([11.22,44,'hi'])) 
     39(([1.0, 2, {'y': [5.0, 6.0], 'x': 1.0}],), {'x': set([11.0, 'hi', 44])}) 
     40""" 
    2341 
    24     #FIXME: see note above... the following is a hack 
    25     def dec(f): 
    26         def func(*args, **kwds): 
    27             _args = [[rounded_arg(arg)[0] for arg in argi] 
    28                      if isiterable(argi) 
    29                      else rounded_arg(argi)[0] 
    30                      for argi in args] 
    31             _kwds = kwds.copy() 
    32             [_kwds.update({kw:[rounded_arg(v)[0] for v in val]}) 
    33                 if isiterable(val) 
    34                 else _kwds.update({kw:rounded_arg(val)[0]}) 
    35                 for (kw,val) in kwds.items()] 
    36             return f(*tuple(_args), **_kwds) 
    37         return func 
    38     return dec 
     42def deep_round(tol=0): 
     43  def dec(f): 
     44    def func(*args, **kwds): 
     45      _deep_round = deep_round_factory(tol) 
     46      _args,_kwds = _deep_round(*args, **kwds) 
     47      return f(*_args, **_kwds) 
     48    return func 
     49  return dec 
    3950 
    4051 
    41 def arg_round(tol=0): 
    42     """Decorator that rounds all floats in args and kwds to given decimal tol. 
    43     """ 
    44     #FIXME: works on foo(1.1111, 2.12345), but not foo([1.1111, 2.12345]) 
    45     def dec(f): 
    46         def func(*args, **kwds): 
    47             _args = list(args) 
    48             _kwds = kwds.copy() 
    49             for i,j in enumerate(args): 
    50                 if type(j)==float: _args[i] = round(j, tol) 
    51             for i,j in kwds.items(): 
    52                 if type(j)==float: _kwds[i] = round(j, tol) 
    53             return f(*tuple(_args), **_kwds) 
    54         return func 
    55     return dec 
     52#FIXME: the below need expiration of cache due to time, calls, etc... 
     53#       and potentially r/w to database, file, or other caching mechanism 
     54#FIXME: memoize*_round fails when decorating a class method 
    5655 
    5756 
     
    6665    memo = {} 
    6766 
    68     @arglist_round(tol) 
     67    @deep_round(tol) 
    6968    def rounded_args(*args, **kwds): 
    7069        return (args, kwds) 
     
    9392    memo = {} 
    9493 
    95     @arglist_round(tol) 
     94    @deep_round(tol) 
    9695    def rounded_args(*args, **kwds): 
    9796        return (args, kwds) 
  • branches/decorate/test_memoize.py

    r535 r581  
    2121""" 
    2222 
     23#from memoize import memoized0_nopickle_round as memoized 
     24#from memoize import memoized0_round as memoized 
    2325#from memoize import memoized0 as memoized 
    2426from memoize import memoized 
Note: See TracChangeset for help on using the changeset viewer.