检查两个Python函数是否相等

检查两个Python函数是否相等,python,function,lambda,Python,Function,Lambda,我想知道如何检查两个函数是否相同。例如,(lambda x:x)==(lambda y:y)计算为true。据我所知,Python将检查函数是否占用内存中的相同位置,但不检查它们是否具有相同的操作。我知道拥有这种功能似乎不切实际 另一个解决方案是我可以在函数上运行某种方法,以查看它包含什么或它是如何工作的。所以有一种(lambda x:x).what(),它将返回方法的工作方式,可能是在字典或其他东西中 我很想得到答案,但我怀疑这是不可能的。您可以测试的一件事是代码对象平等性: >>

我想知道如何检查两个函数是否相同。例如,
(lambda x:x)==(lambda y:y)
计算为true。据我所知,Python将检查函数是否占用内存中的相同位置,但不检查它们是否具有相同的操作。我知道拥有这种功能似乎不切实际

另一个解决方案是我可以在函数上运行某种方法,以查看它包含什么或它是如何工作的。所以有一种
(lambda x:x).what()
,它将返回方法的工作方式,可能是在字典或其他东西中


我很想得到答案,但我怀疑这是不可能的。

您可以测试的一件事是代码对象平等性:

>>> x = lambda x: x
>>> y = lambda y: y
>>> x.__code__.co_code
'|\x00\x00S'
>>> x.__code__.co_code == y.__code__.co_code
True
这里两个函数的字节码是相同的。您可能需要验证代码对象的更多方面(想到常量和闭包),但相等的字节码应该等于相同的执行路径


当然,有一些方法可以创建函数,这些函数为相同的输入返回相同的值,但字节码不同;鱼皮剥皮的方法总是很多。

如果你真的想知道两个函数是否总是对所有输入执行相同的操作,那么你必须在所有输入上同时运行它们(这将花费无限时间),并拦截所有可能的副作用(这实际上是不可能的)

当然,您可以提出一些启发式方法,向它们抛出一组不同的值,对于您的应用程序区域,如果函数不同,很可能会生成不同的输出。但是显然没有通用的解决方案,否则,所有的单元测试都会自动生成,为我们节省了大量的工作,对吗


相反,您可能只想知道两个函数是否具有完全相同的实现。对于这一点,Martijn Pieters的答案是显而易见的起点,甚至可能是终点(取决于您是否关心闭包、全局函数等)


但你所要求的与这两种不同;显然,您希望手动查看代码以查看“它是如何工作的”:

另一个解决方案是我可以在函数上运行某种方法,以查看它包含什么或它是如何工作的。所以有一种(lambda x:x).what()返回方法的工作方式,可能是在字典或其他地方

该函数已存在:。当您在函数上运行它时,它会告诉您该函数是如何工作的。不是在字典中(什么字典?),而是在Python解释器的字节码序列中(这是一个相对简单的堆栈机器,上面添加了一些更高级的东西,主要在
dis
docs中描述)

或者,更简单地说,您可以使用获取源代码

下面是这两个例子的情况:

>>> f1 = lambda x: x
>>> f2 = lambda y: y
>>> def f3(z):
...     return z
>>> dis.dis(f1)
  1           0 LOAD_FAST                0 (x)
              3 RETURN_VALUE
>>> dis.dis(f2)
  1           0 LOAD_FAST                0 (y)
              3 RETURN_VALUE
>>> dis.dis(f3)
  1           0 LOAD_FAST                0 (z)
              3 RETURN_VALUE
>>> inspect.getsource(f1)
'f1 = lambda x: x\n'
>>> inspect.getsource(f2)
'f2 = lambda y: y\n'
>>> inspect.getsource(f3)
'def f3(z):\n    return z\n'

在第一种情况下,您需要充分了解
dis
,以了解
(x)
等不是字节码的一部分,而是函数本地名称列表的一部分。(这在
inspect
文档和
dis
文档中解释得一样多。)在第二种情况下,您需要对Python有足够的了解,以了解
def
lambda
定义的是完全相同的函数。因此,无论哪种方式,都无法实现自动化(或者,实际上,除了Martijn的答案之外的任何东西)。

密切相关:,…尽管Python问题的答案似乎假设不可能直接获取字节码,因此,您必须对其进行反汇编,然后尝试从字节码以外的源代码中去掉反汇编程序添加的所有额外内容,这在实际上完全可能的情况下是愚蠢的(而且要简单得多)为了直接获取字节码……如果其他人来这里了解如何比较同一函数的两个引用:
f==g
对我有效,你也可以创建测试为true但结果不同的对象。(这有点做作,但不管怎样……)@sharth:答案已经包括:“您可能需要验证……”他举了一个闭包的例子。自定义函数属性是另一种。为函数赋予不同的
\uuuu globals\uuu
是另一种选择。我认为我们不需要详尽的列表。
lambda x:x+1
lambda x:x+2
根据这个定义也是相等的。@AndreasMueller:这与abarnert的评论属于同一标题下;在这里,代码对象的
co_consts
元组是不同的。