找出是否已调用函数

时间:2012-03-27 01:42:38

标签: python python-3.x

我正在用Python编程,我想知道我是否可以测试我的代码中是否调用了函数

def example():
    pass
example()
#Pseudocode:
if example.has_been_called:
   print("foo bar")

我该怎么做?

5 个答案:

答案 0 :(得分:25)

如果函数知道自己的名称是可以的,可以使用函数属性:

def example():
    example.has_been_called = True
    pass
example.has_been_called = False


example()

#Actual Code!:
if example.has_been_called:
   print("foo bar")

您还可以使用装饰器来设置属性:

import functools

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

@trackcalls
def example():
    pass


example()

#Actual Code!:
if example.has_been_called:
   print("foo bar")

答案 1 :(得分:1)

自20世纪60年代以来,{p> Memoization功能一直存在。在python中,您可以在 example()函数中将它们用作装饰器。

标准记忆功能如下所示:

def memoize(func):
    memo = {}
    def wrapper(*args):
        if not args in memo:
            memo[args] = func(*args)
        return memo[args]
    return wrapper 

你装饰你的功能:

@memoize
def example():
    pass

在python3.2中,您可以使用functools.lru_cache代替memoziation函数。

import functools

@functools.lru_cache(maxsize=None)
def example():
     pass

答案 2 :(得分:0)

这是一个装饰师,会使用colorama观察你的所有功能,并返回一个不错的输出。

try:
    import colorama
except ImportError:
    class StdClass: pass
    def passer(*args, **kwargs): pass
    colorama = StdClass()
    colorama.init = passer
    colorama.Fore = StdClass()
    colorama.Fore.RED = colorama.Fore.GREEN = ''

def check_for_use(show=False):
    if show:
        try:
            check_for_use.functions
        except AttributeError:
            return
        no_error = True
        for function in check_for_use.functions.keys():
            if check_for_use.functions[function][0] is False:
                print(colorama.Fore.RED + 'The function {!r} hasn\'t been called. Defined in "{}" '.format(function, check_for_use.functions[function][1].__code__.co_filename))
                no_error = False
        if no_error:
            print(colorama.Fore.GREEN + 'Great! All your checked function are being called!')
        return check_for_use.functions
    try:
        check_for_use.functions
    except AttributeError:
        check_for_use.functions = {}
        if colorama:
            colorama.init(autoreset=True)

    def add(function):
        check_for_use.functions[function.__name__] = [False, function]
        def func(*args, **kwargs):
            check_for_use.functions[function.__name__] = [True, function]
            function(*args, **kwargs)
        return func
    return add

@check_for_use()
def hello():
    print('Hello world!')

@check_for_use()
def bonjour(nb):
    print('Bonjour tout le monde!')


# hello(); bonjour(0)

hello()


check_for_use(True) # outputs the following
输出:
Hello world!
The function 'bonjour' hasn't been called. Defined in "path_to_file.py" 

答案 3 :(得分:0)

我们可以使用模拟。模拟

from unittest import mock


def check_called(func):
    return mock.Mock(side_effect=func)


@check_called
def summator(a, b):
    print(a + b)


summator(1, 3)
summator.assert_called()
assert summator.called == True
assert summator.call_count > 0

summator.assert_called_with(1, 3)

summator.assert_called_with(1, 5)  # error
# AssertionError: Expected call: mock(1, 5)
# Actual call: mock(1, 3)

答案 4 :(得分:0)

使用标准库中的unittest.mock.Mock的一个最小示例:

from unittest.mock import Mock

def example():
    pass

example_mock = Mock(side_effect=example)
example_mock()
#Pseudocode:
if example_mock.called:
   print("foo bar")

运行脚本后控制台输出:

foo bar

这种方法很好,因为它不需要您修改example函数本身,如果您想在某些单元测试代码中执行此检查而无需修改源代码本身(例如,EG存储has_been_called属性,或将函数包装在装饰器中。

说明

the documentation for the unittest.mock.Mock class中所述,side_effect构造函数的Mock()参数指定“每当调用Mock时都要调用的函数”。

Mock.called属性指定“一个表示是否已调用模拟对象的布尔值”。

Mock类还具有其他可能有用的属性,例如EG:

call_count:一个整数,告诉您模拟对象被调用了多少次

call_args:这是“无”(如果尚未调用该模拟),或者是上次使用该模拟调用的参数

call_args_list:这是按顺序对模拟对象进行的所有调用的列表(因此列表的长度是其被调用的次数)。在进行任何呼叫之前,它是一个空列表

Mock类还具有方便的方法,可根据调用Mock对象的次数以及使用EG调用的参数来制作断言语句:

assert_called_once_with(*args, **kwargs):断言该模拟只被调用了一次,并且该调用带有指定的参数