在另一个方法中计算python方法调用

job*_*job 12 python profiling

我实际上是在尝试用Java做这个,但我正在自学python的过程中,这让我想知道是否有一个简单/聪明的方法用包装器或其他东西来做这件事.

我想知道在另一个方法中调用特定方法的次数.例如:

def foo(z):
    #do something
    return result

def bar(x,y):
    #complicated algorithm/logic involving foo
    return foobar
Run Code Online (Sandbox Code Playgroud)

所以对于每次使用各种参数调用bar,我想知道foo被调用了多少次,也许是这样的输出:

>>> print bar('xyz',3)
foo was called 15 times
[results here]
>>> print bar('stuv',6)
foo was called 23 times
[other results here]
Run Code Online (Sandbox Code Playgroud)

编辑:我意识到我可以在栏内打一个计数器并在我返回时将其转储,但如果有一些魔法可以用包装来完成同样的事情,那将会很酷.这也意味着我可以在其他地方重用相同的包装器,而无需修改方法中的任何代码.

bob*_*nce 20

听起来几乎像装饰者的教科书示例!

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
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用另一个装饰器自动记录在另一个函数中调用函数的次数:

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
Run Code Online (Sandbox Code Playgroud)

但是,如果foo或者bar最终会调用自己,那么您需要一个更复杂的解决方案来处理堆栈以应对递归.那么你正在走向一个全面的剖析器......

可能这个包装装饰的东西,往往被用于魔术,如果你仍然'教自己Python',它不是一个理想的地方!


Ned*_*der 7

这定义了一个装饰器来做它:

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
Run Code Online (Sandbox Code Playgroud)