Here are a few ideas (including a meta-decoration! :) Of course, I'm biased to first-before-colon style. ;) --- decorators.py --- import inspect class decorator: """ An obscenely gratuitous example of decorator usage. Meta-decoration? "One mans use is another man's abuse" """ class decoration: """ The object that represents the decoration itself. """ def __init__(decor, func, **state): self.func = func self.state = {'func': func.__name__} def __call__(self, *args, **kwds): """ Called when the function that is decorated by this decoration is called. (whew) """ self.state.update(inspect.getargvalues(sys._getframe(1))[3]) # better way? return self.decor(self.func, self.state, *args, **kwds) def options(self, opts=None, **kwd_opts): self.state.update(opts or kwd_opts) return self def __init__(self, decor): self.decor = decor def __call__(self, func): """ Called when the decorator is called to decorate a desired function. """ init = self.init init.update(kwds) return self.decoration(decor, func) def fromstate(cls, state=None, **kwd_state) [classmethod]: """ Make a decoration with a specified initial state """ return lambda fn: cls(fn, state or kwd_state) # or... # Smaller, but can be confusing. (But I guess the whole # meta-function-generator thing is to begin with!) def decorator2(decor=None, **state): """ Decoration factory. """ def decoration2(func=None, **opts): """ Decorating function wrapper. """ state.update(opts) state['func'] = func.__name__ def callit(*args, **kwds): """ Function replacement. """ state.update(inspect.getargvalues(sys._getframe(1))[3]) # better way? decor(func, state, *args, **kwds) if func: return callit else: return lambda fn: decoration2(fn, **opts) if decor: return decoration else: return lambda dec: decorator2(dec, state) def memoized(func, state, *args, **kwds) [decorator]: """ Function wrapper to cache the results of previously evaluated arguments. """ items = kwds.items items.sort() key = (args, tuple(items)) # hope everything is hashable! return ( state.get(key) or state.setdefault(key, func(*args, **kwds)) ) def memoized2(func, state, *args, **kwds) [decorator2]: key = (args, tuple(kwds.items())) return ( state.get(key) or state.setdefault(key, func(*args, **kwds)) ) import sys, time def logged(func, state, *args, **kwds) [decorator.fromstate( output=sys.stdout.write, prefix='%(func)s: ')]: """ Usage for default formatting and output: def func(*args) [logged]: pass Usage for custom formatting and output: def func(a, b) [logged.options(output=output_func, prefix="%(func)s %(a)s %(b)i")]: pass String replacements include 'func' which is the function's name, as well as all arguments to the function such that "%(a)s" would become the value of the argument named 'a'. """ p = '[%s] %s' % (time.time(), state['prefix'] % state) state['output'](p) def logged2(func, state, *args, **kwds) [decorator2( output=sys.stdout.write, prefix='%(func)s: ')]: """ Usage for default formatting and output: def func(*args) [logged2]: pass Usage for custom formatting and output: def func(a, b) [logged2(output=output_func, prefix="%(func)s %(a)s %(b)i")]: pass String replacements include 'func' which is the function's name, as well as all arguments to the function such that "%(a)s" would become the value of the argument named 'a'. """ p = '[%s] %s' % (time.time(), state['prefix'] % state) state['output'](p) # demo function def factorial(n) [memoized, logged.options(output=sys.stdout.write, prefix='factorial for %(n)s: ')]: """ Computes the factorial of n """ print "fact(%i)" % n if n == 1: return 1 else: return n * fact(n - 1) # make tail_recursive decorator(?) def factorial2(n) [memoized, logged2(output=sys.stdout.write, prefix='factorial for %(s): ')]: """ Computes the factorial of n """ print "fact(%i)" % n if n == 1: return 1 else: return n * fact(n - 1)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4