前言

每当做搜索任务或者时间复杂度任务相关时候,就会有统计函数被调用次数的需求。通常我们的做法是在函数前面定义一个变量,每循环调用一次,变量就加一,这不失为一种办法,那么有没有更高效的方法呢?

正文

第一种方法:

当然有,那就是python的独家专属操作—> 装饰器。
废话不多说,直接上例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CallingCounter(object):
def __init__ (self, func):
self.func = func
self.count = 0

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

@CallingCounter
def test():
print('我被调用了')

test()
print(f'我被调用了{test.count}次')

如果是统计class中的函数被调用的次数,就把 装饰器 装在被调用函数的前面即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class CallingCounter(object):
def __init__ (self, func):
self.func = func
self.count = 0

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

class Test:
@CallingCounter
def test():
print('我被调用了')

for i in range(10):
Test.test()

print(f'我被调用了{Test.test.count}次')

如果你的class中有很多的self用来调用函数,那么可能会报错,提示self无xxx属性or函数。这时候就要看第二种方法

第二种方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def call_counter(func):
def helper(*args, **kwargs):
helper.calls += 1
return func(*args, **kwargs)
helper.calls = 0
helper.__name__= func.__name__
return helper

# 下面是使用装饰器
@call_counter
def f():
pass
print(f.calls)

for _ in range(10):
f()
print(f.calls)
# 0 10

# 这里是另一种调用方式
def f():
pass
f = call_counter(f)
print(f.calls)

for _ in range(10):
f()
print(f.calls)
# 0 10

上面两种方法笔者都亲自做了测试,下面再介绍3个超简单的(狗头保命)

第3.1种方法(超简单)

1
2
3
4
5
6
7
8
calls = 0

def f():
global calls
calls += 1
# do your func stuff here

## 如果想统计class中的函数使用次数,同理

第3.2种方法(超简单)

1
2
3
4
5
6
class Test(object):
def __init__(self):
self.calls = 0
def f(self):
self.calls += 1
# do your func stuff here

第3.3种方法(超简单)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Test(object):
calls = 0
def __init__(self):
pass
def f(self):
Test.calls += 1
# do your func stuff here

# 调用方式
# Test().f()

A = Test()
for i in range(10):
A.f()
print(A.calls)
print(Test().calls)
print(Test.calls)

小结

还瞅啥,好用了就赶紧去用吧。好用回来点个赞。

本文将原创进行了整理,尊重原创,附链接1链接2