文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

去年我碰到一个这样的问题,我需要知道某个函数是否被调用过。一般我们会试图阻止两次关闭或者启动 Twisted 事件循环。最后我无意中在 StackOverflow 发布了一个有意思的帖子,然后就知道了很多种方法来实现我的需求。

首先,Python 里所有东西都是对象,包括函数本身。因此我们来看看下面这个简单的例子:

def self_aware_function(a, b):
    self_aware_function.has_been_called = True
    return a + b

if __name__ == '__main__':
    self_aware_function.has_been_called = False

    for i in range(2):
        if self_aware_function.has_been_called:
            print 'function already called'
        else:
            print 'function not called'

        self_aware_function(1, 2)
第 1 段(可获 1.05 积分)

在这个例子中,我在函数中创建了一个 has_been_called 属性,并在函数被调用时设置为 True。当启动程序时,我们需要将其设置为 False,如上代码所示。然后我们使用一个 for 循环来执行两次函数。第一次执行时将会检查该函数是否被调用过。如果还没有,就进入 else 语句,然后执行函数。循环执行第二次的时候就进入 if 语句部分的执行。

StackOverflow 的帖子同时还提到了一个更简洁的方法就是使用修饰符来跟踪函数调用。我写了一个简单例子如下:

第 2 段(可获 1.54 积分)
import functools


def calltracker(func):
    @functools.wraps(func)
    def wrapper(*args):
        wrapper.has_been_called = True
        return func(*args)
    wrapper.has_been_called = False
    return wrapper

@calltracker
def doubler(number):
    return number * 2

if __name__ == '__main__':
    if not doubler.has_been_called:
        print "You haven't called this function yet"
        doubler(2)

    if doubler.has_been_called:
        print 'doubler has been called!'

在这个例子中,我导入了 functools 并创建一个修饰器,名为 calltracker。 在这个函数中,我们设置了跟前面例子中一样的属性,但与之不同的是我们将其绑定到我们的封装器中(修饰器)。然后我们对一个函数就行修饰并测试代码。首个 if 语句检查函数是否被调用,如果没有则继续执行函数。紧接着我们就可以确认函数是否已经被调用过。

第 3 段(可获 1.15 积分)

结束

虽然这东西肯定在运行时是有用的,你还可以使用 Python 的 trace 模块来跟踪代码的执行。这种需求也可以通过覆盖工具来完成。你可以在 Python Mock objects 中找到这种功能类型来实现函数调用的模拟。

不管怎样,希望你觉得我这个小练习很有趣。虽然我早知道 Python 里一切都是对象,但我都没想过可以为一个函数增加属性。

第 4 段(可获 1.21 积分)

文章评论

中山狼
很简单的一篇文章