有没有办法跟踪调用函数的次数?

时间:2014-02-12 01:41:05

标签: python

所以我正在尝试创建一个跟踪方法调用次数的函数。 例如:

a = [1,2,3,4]
a.pop()

我想知道到目前为止a.pop()被调用了多少次,所以对于这个例子,我会得到1。 有没有办法做到这一点?

12 个答案:

答案 0 :(得分:35)

这对内置函数不起作用,但有趣的方法是:

def myfunction():
    myfunction.counter += 1
myfunction.counter = 0

您为该函数提供了一个属性,因此每次调用该属性都会更新。不需要全局变量。

内置命令是只读的。它们无法修改。

答案 1 :(得分:25)

您可以使用装饰器跟踪调用函数的次数。由于list是内置的,因此您无法修饰或替换其pop方法,因此您必须使用自己的列表类。例如。

def counted(f):
    def wrapped(*args, **kwargs):
        wrapped.calls += 1
        return f(*args, **kwargs)
    wrapped.calls = 0
    return wrapped

class MyList(list):
    @counted
    def pop(self, *args, **kwargs):
        return list.pop(self, *args, **kwargs)

x = MyList([1, 2, 3, 4, 5])
for i in range(3):
    x.pop()

print x.pop.calls # prints 3

答案 2 :(得分:13)

我使用以下小技巧来跟踪函数被调用的次数

def myfun(s,i=[0]):    
    print(s)    
    i[0]+=1 # mutable variable get evaluated ONCE
    return i[0]

>>> myfun('aaa')
aaa
1
>>> myfun('bbb')
bbb
2

答案 3 :(得分:3)

对于踢球,我使用装饰师写了一个答案:

class counter:
    #wraps a function, to keep a running count of how many
    #times it's been called
    def __init__(self, func):
        self.func = func
        self.count = count

    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.func(*args, **kwargs)

要使用它,只需装饰一个功能。然后,您可以通过检查“count”属性来检查该函数的运行次数。这样做很好,因为:

1。)没有全局变量。计数与函数直接相关。

2。)您可以通过直接调用类来轻松包装内置函数:

sum_wrapped = counter(sum)
sum_wrapped([1, 2 ,3, 4])
#outputs 10
print sum_wrapped.count
#outputs 1

当然,可以通过使用Decorators模块来保持文档字符串和其他好东西的完整性。此外,为了更好地了解装饰器是什么以及它们如何工作,请查看this stackoverflow answer

答案 4 :(得分:2)

一种方法是创建要为其计算属性访问权的实例的代理:

from collections import Counter

class CountingProxy():
    def __init__(self, instance):
        self._instance = instance
        self.count = Counter()

    def __getattr__(self, key):
        if hasattr(self._instance, key):
            self.count[key] += 1
        return getattr(self._instance, key)


>>> l = [1,2,3,4,5]
>>> cl = CountingProxy(l)
>>> cl.pop()
5
>>> cl.append(10)
>>> cl.index(3)
2
>>> cl.reverse()
>>> cl.reverse()
>>> cl.count
Counter({'reverse': 2, 'pop': 1, 'append': 1, 'index': 1})

答案 5 :(得分:1)

一种简单的方法是每次调用函数时递增一个全局变量。

counter = 0

a = [1,2,3,4]    
a.pop()
counter += 1

答案 6 :(得分:1)

counter = 0

def pop():
  counter += 1
  print counter
  #other function code

a = [1,2,3,4]  
a.pop()

这可以解决您的问题,您应该能够看到计算的是什么。 + 每次调用该函数时,计数器都会增加,并且每次传递函数都会打印出来。

如果它内置:

    counter = 0
    def newfunction():
      a = [1,2,3,4]  
      a.pop()
      counter += 1
      print counter

这里的逻辑是它将调用你的新函数进入预制的函数,然后退出内置函数,然后继续将计数器标记为增加。输出你的计数器。

答案 7 :(得分:0)

这是一种用于自计数功能的简单且优雅的解决方案,无需任何装饰器,全局变量等:

def hello():
    hello.counter += 1
    print(hello.counter)
hello.counter = 0

每次调用hello()时,它将打印12等。

  

让我们不要忘记,在Python中,函数是一等公民   它拥有权利。其中之一就是拥有属性!

如果您愿意在函数中包含方法调用,则可能很容易:

def pop_counted(a):
    pop_counted.counter += 1
    return a.pop()
pop_counted.counter = 0

Voilà

评论

之所以有效,是因为Python函数本身“知道”(这是必要的功能,因此如果需要,函数可以递归调用它们)。

如果您希望保留有关某个功能的某些信息,则最好将其保留在其所属位置:在该功能的属性中。

使用全局变量的优势是范围:

  • 在全局名称空间中没有名称冲突的风险
  • 您将要保留的信息将在函数被从堆栈中删除后立即消失,这就是您想要的-没有剩余的垃圾。

一个好处是,这种方法在全局变量不是真正好的选择的情况下会起作用,通常适用于无法在外部函数中声明“全局”的嵌套函数。

答案 8 :(得分:0)

只需在函数中定义全局语句即可。

count = 1
def your_func():
  global count
  print(count)
  count= count +1

答案 9 :(得分:0)

我是通过复制JavaScript console.count()方法的工作方式来完成的。那是我的代码:

class Terminal(object):
    __count_names = []
    def count(self, name='default'):
        # check if name already exists
        i = next((self.__count_names.index(item) for item in self.__count_names if item['name'] == name), None)
        # if name argument does not exist register it
        if i is None:
            dictionary = { 'name': name, 'count': 1 }
            self.__count_names.append(dictionary)
        # if exists increment 'count'
        else:
            dictionary = self.__count_names[i]
            dictionary['count'] += 1
            self.__count_names[i] = dictionary
        # finally print name and count
        print(f"{dictionary['name']} : {dictionary['count']}")

您的代码应如下所示:

terminal = Terminal()
def myFunc():
    terminal.count("myFunc")

myFunc()
myFunc()
myFunc("myFunc")

输出:

myFunc: 1
myFunc: 2
myFunc: 3
myFunc: 4

答案 10 :(得分:0)

来自 Datacamp 的示例,使用装饰器:

def counter(func):
  def wrapper(*args, **kwargs):
    wrapper.count += 1
    # Call the function being decorated and return the result
    return func(*args, **kwargs)
  wrapper.count = 0
  # Return the new decorated function
  return wrapper

# Decorate foo() with the counter() decorator
@counter
def foo():
  print('calling foo()')
  
foo()
foo()

print('foo() was called {} times.'.format(foo.count))

# output
calling foo()
calling foo()
foo() was called 2 times. 

答案 11 :(得分:-1)

只需定义一个全局变量并将其在函数内部递增。

a = 0
def some_function():
    global a
    a+=1
    <..Your code.>

此功能会随着使用功能的增加而自动递增,并且您可以全局访问它。