I\'m actually trying doing this in Java, but I\'m in the process of teaching myself python and it made me wonder if there was an easy/clever way to do this with wrappers or
This defines a decorator to do it:
def count_calls(fn):
    def _counting(*args, **kwargs):
        _counting.calls += 1
        return fn(*args, **kwargs)
    _counting.calls = 0
    return _counting
@count_calls
def foo(x):
    return x
def bar(y):
    foo(y)
    foo(y)
bar(1)
print foo.calls
After your response - here's a way with a decorator factory...
import inspect
def make_decorators():
    # Mutable shared storage...
    caller_L = []
    callee_L = []
    called_count = [0]
    def caller_decorator(caller):
        caller_L.append(caller)
        def counting_caller(*args, **kwargs):
            # Returning result here separate from the count report in case
            # the result needs to be used...
            result = caller(*args, **kwargs)
            print callee_L[0].__name__, \
                   'was called', called_count[0], 'times'
            called_count[0] = 0
            return result
        return counting_caller
    def callee_decorator(callee):
        callee_L.append(callee)
        def counting_callee(*args, **kwargs):
            # Next two lines are an alternative to
            # sys._getframe(1).f_code.co_name mentioned by Ned...
            current_frame = inspect.currentframe()
            caller_name = inspect.getouterframes(current_frame)[1][3]
            if caller_name == caller_L[0].__name__:
                called_count[0] += 1
            return callee(*args, **kwargs)
        return counting_callee
    return caller_decorator, callee_decorator
caller_decorator, callee_decorator = make_decorators()
@callee_decorator
def foo(z):
    #do something
    return ' foo result'
@caller_decorator
def bar(x,y):
    # complicated algorithm/logic simulation...
    for i in xrange(x+y):
        foo(i)
    foobar = 'some result other than the call count that you might use'
    return foobar
bar(1,1)
bar(1,2)
bar(2,2)
And here's the output (tested with Python 2.5.2):
foo was called 2 times
foo was called 3 times
foo was called 4 times
Sounds like almost the textbook example for decorators!
def counted(fn):
    def wrapper(*args, **kwargs):
        wrapper.called += 1
        return fn(*args, **kwargs)
    wrapper.called = 0
    wrapper.__name__ = fn.__name__
    return wrapper
@counted
def foo():
    return
>>> foo()
>>> foo.called
1
You could even use another decorator to automate the recording of how many times a function is called inside another function:
def counting(other):
    def decorator(fn):
        def wrapper(*args, **kwargs):
            other.called = 0
            try:
                return fn(*args, **kwargs)
            finally:
                print '%s was called %i times' % (other.__name__, other.called)
        wrapper.__name__ = fn.__name__
        return wrapper
    return decorator
@counting(foo)
def bar():
    foo()
    foo()
>>> bar()
foo was called 2 times
If foo or bar can end up calling themselves, though, you'd need a more complicated solution involving stacks to cope with the recursion. Then you're heading towards a full-on profiler...
Possibly this wrapped decorator stuff, which tends to be used for magic, isn't the ideal place to be looking if you're still ‘teaching yourself Python’!