关于反射:检查两个python函数(或方法)的兼容性

Checking compatibility of two python functions (or methods)

是否有可能检查两个python函数是否可以互换? 例如,如果我有

1
2
3
4
5
6
def foo(a, b):
    pass
def bar(x, y):
    pass
def baz(x,y,z):
    pass

我想要一个函数is_compatible(a,b),当传递foo和bar时返回True,但是当传递bar和baz时返回False,所以我可以在实际调用其中任何一个之前检查它们是否可以互换。


你会以什么兼容性为基础?争论的数量? Python有可变长度的参数列表,所以你永远不知道两个函数在这个意义上是否兼容。数据类型? Python使用duck typing,因此在函数内部使用isinstance测试或类似函数之前,对兼容性测试可能基于的数据类型没有约束。

简而言之:不。

你应该写好文档字符串,这样你的API的任何用户都知道他给你的功能是什么,然后你应该相信你得到的函数行为正确。任何"兼容性"检查都会排除可能有效的功能,或者让你误解"一切都应该如此"。

暴露API的pythonic方式是:编写好的文档,以便人们知道他们需要知道什么,并相信他们做正确的事情。在关键位置,您仍然可以使用try: except:,但是任何滥用您的API的人,因为他们只是不关心阅读文档,不应该给予错误的安全感。而那些确实阅读过您的文档并希望以完全可接受的方式使用它的人不应该被拒绝以他们宣布函数的方式使用它的可能性。


看看inspect.getargspec()

inspect.getargspec(func)

Get the names
and default values of a function’s
arguments. A tuple of four things is
returned: (args, varargs, varkw,
defaults). args is a list of the
argument names (it may contain nested
lists). varargs and varkw are the
names of the * and ** arguments or
None. defaults is a tuple of default
argument values or None if there are
no default arguments; if this tuple
has n elements, they correspond to the
last n elements listed in args.

Changed in version 2.6: Returns a
named tuple ArgSpec(args, varargs,
keywords, defaults).