[omaha] Decorators

Jeff Hinrichs - DM&T jeffh at dundeemt.com
Tue Jan 15 15:27:57 CET 2008


On 1/14/08, Eli Criffield <elicriffield at gmail.com> wrote:
> > Decorators in python are syntactic sugar to let you wrap a
> > function/method with another function.
>
> How would you do the same thing a decorator does without using a decorators.

"Function Decorators by Hacking Bytecodes"
  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286147

DecoratorTools
  http://pypi.python.org/pypi/DecoratorTools/1.7

> > http://www.phyast.pitt.edu/~micheles/python/documentation.html  you'll
> > get a feel for why the function signature might be meaningful to you
>
> Ok whats a function signature, and why would it change, or even stay the same?
>
> Eli
so here is an example of a decorator that I grabbed from
http://wiki.python.org/moin/PythonDecoratorLibrary

#!/usr/bin/env python

from inspect import getargspec

def dumpArgs(func):
    "This decorator dumps out the arguments passed to a function
before calling it"
    argnames = func.func_code.co_varnames[:func.func_code.co_argcount]
    fname = func.func_name
    def echoFunc(*args,**kwargs):
        print fname, ":", ', '.join('%s=%r' % entry
                                    for entry in zip(argnames,args) +
kwargs.items())
        return func(*args, **kwargs)
    return echoFunc

@dumpArgs
def f1(a,b,c):
    print a + b + c

def f2(a,b,c):
    print a + b + c

f1(1, 2, 3)
f2(1, 2, 3)

print getargspec(f1)
print getargspec(f2)


The output generated looks like:
f1 : a=1, b=2, c=3
6
6
([], 'args', 'kwargs', None)
(['a', 'b', 'c'], None, None, None)

Both functions f1 and f2 take and compute the same thing.  They should
have the same function signature.  But looking at the output of
getargspec for the two functions show two different things. the
decorated function, f1, appears to take an unlimited number of
args/keywordargs where as the  undecorated function, f2 shows that it
takes 3 values, named a,b and c.

If you use an editor that supports (i forget the exact name) parameter
help pop-ups, it's using the function signature to help you out by
telling you what input parameters are being expected.  Other code
inspection tools and pydoc will give you incorrect information too.

using the decorator module (easy_install decorator) that Eli was
talking about, you get:
#assumes you have easy_installed the 3rd party decorator module

from decorator import decorator

@decorator
def dumpArgs2(f, *args, **kw):
    argnames = f.func_code.co_varnames[:f.func_code.co_argcount]
    fname = f.func_name
    print fname, ":", ', '.join('%s=%r' % entry
                                    for entry in zip(argnames,args) +
kw.items())
    return f(*args, **kw)

@dumpArgs2
def f3(a,b,c):
    print a+b+c

f3(1,2,3)
print getargspec(f3)

Which results in:
f3 : a=1, b=2, c=3
6
(['a', 'b', 'c'], None, None, None)

You'll notice that the function signature now matches the undecorated
function.  This means pydoc and other code inspection tools are now
able to return useful information.

-jeff


More information about the Omaha mailing list