断言是Python中的有效函数

时间:2013-12-14 02:05:28

标签: python unit-testing

假设我有以下代码,它接受一个距离函数和两个点,并吐出距离:

def distance(dist_fun, p1, p2):
    ## SOME ASSERTION HERE on dist_fun ##

    ## Suppose, just for this post, we've already checked p1 and p2 are 
    ## n-tuples of integers.

    assert (len(p1) == len(p2)), "Coordinates are different dimensions."
    dist = dist_fun(p1, p2)
    assert (dist>=0), "Negative distance is not possible."
    return dist

def euclid(p1, p2):  #as an example dist function.
    return pow(reduce(lambda x,y: x+y, [pow((p1[i] - p2[i]), 2) for i in range(len(p1))]),0.5)

我希望能够检查用户是否使用特定的距离函数,首先是实际上是函数。在此之后,我可以查看其他内容,但我的主要问题是:我如何断言dist_fun实际上是一个函数?

如果没有简单的方法可以做到这一点,或者有其他办法可以做到这一点,请告诉我。我以前在Python中做过一些测试,但直到现在才遇到过这个问题。我已经看到函数的“类型”是“函数”,但是Python不允许我将它用作类型?除了这里之外,回去尝试会更容易吗?

4 个答案:

答案 0 :(得分:5)

Python的座右铭当然是,请求宽恕而不是许可更好。所以,你完全可以指望用户传递有效的输入,或except TypeError如果你试图调用无法调用的东西而被抛出的assert (callable(dist_fun))

那就是说,如果你真的想断言某事是一个功能,我想你总能检查一下这个类型......

{{1}}

答案 1 :(得分:1)

  

我怎么断言dist_fun实际上是一个函数?

通常通过以下方式完成:

if callable(f):
    ...

答案 2 :(得分:1)

如果你想断言它实际上是一个函数,那很容易:

assert ininstance(dist_fun, types.FunctionType)

......或:

assert inspect.isfunction(dist_fun)

一般来说,遇到这个问题时:

  

我已经看到函数的“类型”是“函数”,但Python不允许我将它用作类型?

...对于内置类型,types中提供了您想要的类型和/或可以在inspect中找到更简单检查的函数。


然而,你可能不想这样做;相反,你想断言它是可以调用的东西。毕竟,绑定方法,functools.partial,具有自定义__call__方法的对象,在C扩展中实现的自定义函数类对象等都在这里同样有用,对吧?所以使用callable

assert callable(dist_fun)

(除非您需要支持Python 3.0-3.1,或者非常古老的1.x版本。callable在1.4左右添加,在3.0中删除,然后在3.2中添加。)


或者,甚至更好(仅限Python 3.3+):

assert inspect.signature(dist_fun).bind(p1, p2)

这会检查它不仅可以调用,而且可以使用要传递它的参数调用。 (当它只是两个位置参数时,这不是什么大问题......但是当你传递关键字参数,或者使用 / *等转发args时,它可以是。)

答案 3 :(得分:0)

好吧,不是试图测试参数是否是一个有效的函数,你可以测试它是否可调用,因为使用python任何用户都可以使用可调用而不是函数,这是一种方法:

if callable(dist_fun):
    # do whatever you wanna do

assert callable(dist_func)