[Python-Dev] Re: PEP 318: Let's propose some useful built-in decorators (original) (raw)

Isaac Freeman ishnigarrab at earthlink.net
Sat Apr 3 19:00:38 EST 2004


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'

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'

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)



More information about the Python-Dev mailing list