【问题标题】:Counting calls and maximum recursive depth by a decorator in pythonpython中装饰器计算调用和最大递归深度
【发布时间】:2021-03-16 14:50:05
【问题描述】:

我想要一个有两个字段的装饰器,比如说.ncalls.rdepth。当它包装一个函数时,ncalls 应该计算函数调用自身的次数,如果函数是递归的,rdepth 应该表示达到的最大递归深度。 我已经尝试过类似这里 (https://stackoverflow.com/a/51690214/12313533) 但它不起作用。 我的代码现在看起来像是前面提到的代码和使用装饰器计算函数调用的代码的混合体:

def call_counter(func): #a decorator to count calls
    def helper(x):
        helper.calls += 1
        return func(x)
    helper.calls = 0
    return helper

所以我需要这样的东西(这不起作用):

def depthcounter(func):
     def wrapper(*args, **kwargs):
         wrapper.rdepth += 1
         wrapper.ncalls += 1
         result = func(*args, **kwargs)
         return result
     wrapper.ncalls = 0
     wrapper.rdepth = 0
     return wrapper

例如,假设我有一个阶乘生成函数,例如

@depthcounter
def factorial(n):
    if n <= 1:
        return 1
    else:
        return n * factorial(n - 1)

#Here is some working code

print(factorial.ncalls, factorial.rdepth)
factorial(4)
print(factorial.ncalls, factorial.rdepth)
factorial(10)
print(factorial.ncalls, factorial.rdepth)
print(factorial.ncalls, factorial.rdepth)
factorial(20)
print(factorial.ncalls, factorial.rdepth)
factorial(2)
print(factorial.ncalls, factorial.rdepth)

我需要使用装饰器来制作这个:

0 0
4 4
10 10
10 10
20 20
2 2

但我得到了这个:

0 0
4 4
14 14
14 14
34 34
36 36

【问题讨论】:

  • 你使用什么值来调用factorial
  • 4、10 和 20。抱歉,忘记添加了。我在问题中编辑了一些代码
  • 你基本上想在每次运行后重置值

标签: python recursion decorator


【解决方案1】:

装饰器在导入模块后立即执行,因此您的赋值 wrapper.ncalls = 0 只执行一次,而不是在每次函数调用时执行。 您需要跟踪 wrapper 函数内的起始计数。这是一段工作代码:

def callcounter(func):
    callcounter.ncalls  = 0
    def wrapper(*args, **kwargs): 
        initial_calls = callcounter.ncalls
        callcounter.ncalls += 1
        result = func(*args, **kwargs)
        wrapper.ncalls = callcounter.ncalls - initial_calls
        return result
    return wrapper

@callcounter
def factorial(n):
    if n <= 1:
        return 1
    else:
        return n * factorial(n - 1)

factorial(4)
print(factorial.ncalls)
factorial(10)
print(factorial.ncalls)

输出

4
10

【讨论】:

    猜你喜欢
    • 2011-03-01
    • 2019-01-12
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    相关资源
    最近更新 更多