Self-identifying functions and macro-ish behavior

Ben Cartwright bencvt at gmail.com
Wed Feb 15 10:51:14 EST 2006


63q2o4i02 at sneakemail.com wrote:
> How do I get some
> sort of macro behavior so I don't have to write the same thing over and
> over again, but which is also not neatly rolled up into a function,
> such as combining the return statements with a printing of <self-name>?


Decorators: http://www.python.org/peps/pep-0318.html


> My application has a bunch of functions that must do different things,
> then print out their names, and then each call another function before
> returning.  I'd like to have the last function call and the return in
> one statement, because if I forget to manually type it in, things get
> messed up.
>
> (ok, I'm writing a parser and I keep track of the call level with a tab
> count, which gets printed before any text messages.  So each text
> message has a tab count in accordance with how far down the parser is.
> Each time a grammar rule is entered or returned from, the tab count
> goes up or down.  If I mess up and forget to call tabsup() or tabsdn(),
> the printing gets messed up.  There are a lot of simple cheesy
> production rules, [I'm doing this largely as an exercise for myself,
> which is why I'm doing this parsing manually], so it's error-prone and
> tedious to type tabsup() each time I enter a function, and tabsdn()
> each time I return from a function, which may be from several different
> flow branches.)


def track(func):
    """Decorator to track calls to a set of functions"""
    def wrapper(*args, **kwargs):
        print " "*track.depth + func.__name__, args, kwargs or ""
        track.depth += 1
        result = func(*args, **kwargs)
        track.depth -= 1
        return result
    return wrapper
track.depth = 0


# Then to apply the decorator to a function, e.g.:
def f(x):
    return True
# Add this line somewhere after the function definition:
f = track(f)

# Alternately, if you're using Python 2.4 or newer, just define f as:
@track
def f(x):
    return True


# Test it:
@track
def fact(n):
    """Factorial of n, n! = n*(n-1)*(n-2)*...*3*2"""
    assert n >= 0
    if n < 2:
        return 1
    return n * fact(n-1)
@track
def comb(n, r):
    """Choose r items from n w/out repetition, n!/(r!*(n-r)!)"""
    assert n >= r
    return fact(n) / fact(r) / fact(n-r)
print comb(5, 3)
# Output:
"""
comb (5, 3)
 fact (5,)
  fact (4,)
   fact (3,)
    fact (2,)
     fact (1,)
 fact (3,)
  fact (2,) 
   fact (1,) 
 fact (2,) 
  fact (1,) 
10
"""

--Ben




More information about the Python-list mailing list