我想知道如何检查两个功能是否相同。一个例子是(lambda x: x) == (lambda y: y)
评估为真。据我所知,Python将检查函数是否占用内存中的相同位置,但不检查它们是否具有相同的操作。我知道拥有这个功能似乎不切实际。
另一个解决方案是我可以在函数上运行的一些方法来查看它包含的内容或它的工作原理。所以有一种(lambda x: x).what()
可以返回方法的工作方式,可能是在字典或其他东西。
我很想回答,但我怀疑这是可能的。
答案 0 :(得分:30)
您可以测试的一件事是代码对象相等:
>>> x = lambda x: x
>>> y = lambda y: y
>>> x.__code__.co_code
'|\x00\x00S'
>>> x.__code__.co_code == y.__code__.co_code
True
这两个函数的字节码是相同的。您可能需要验证代码对象的更多方面(常量和闭包),但相等的字节码应该等于相同的执行路径。
当然有一些方法可以创建为同一输入返回相同值但具有不同字节码的函数;总是有更多的方法来养鱼。
答案 1 :(得分:9)
如果你真的想知道两个函数是否总是对所有输入执行相同的操作,则必须在所有输入上运行它们(这将花费无限时间),并且还拦截所有可能的副作用(这是有效的不可能的)。
你当然可以提出一些启发式方法,为它们抛出一组不同的值,对于你的应用领域,如果功能不同,它们很可能产生不同的输出。但显然没有通用的解决方案 - 否则,所有的单元测试都会自动生成,为我们节省了大量的工作,对吗?
相反,您可能只想知道两个函数是否具有完全相同的实现。为此,Martijn Pieters的答案是明显的起点,甚至可能是结束点(取决于你是否关心闭包,全局等)。
但你所要求的是与这两者不同的东西;你显然想手动查看代码以查看“它是如何工作的”:
另一个解决方案是我可以在函数上运行的一些方法来查看它包含的内容或它的工作原理。所以一种(lambda x:x).what()会返回该方法的工作方式,可能是在字典或其他东西。
该功能已存在:dis.dis
。在函数上运行它时,它会告诉您该函数的工作原理。不是在字典中(字典是什么?)而是在Python解释器的一系列字节码行中(这是一个相对简单的堆栈机器,顶部添加了一些更高级别的东西,大部分都在{{1文档)。
或者,更简单地说,您可以使用inspect.getsource
来获取来源。
以下是您的示例中的两个外观:
dis
在第一种情况下,您需要充分了解>>> 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
文档中的内容相同。第二,您需要充分了解Python才能实现dis
和{{1定义完全相同的函数。因此,无论哪种方式,都无法自动化(或者,实际上,远远超出Martijn的答案)。