我试图编写一个测试,检查保存类的绑定方法的变量是否与该方法的另一个引用相同.通常这不是问题,但在同一类的另一个方法中完成时似乎不起作用.这是一个最小的例子:
class TestClass:
def sample_method(self):
pass
def test_method(self, method_reference):
print(method_reference is self.sample_method)
Run Code Online (Sandbox Code Playgroud)
我真的使用的是assert代替print,但是既不是在这里也不是在那里,因为最终的结果是相同的.测试运行如下:
instance = TestClass()
instance.test_method(instance.sample_method)
Run Code Online (Sandbox Code Playgroud)
结果是False即使我期待它True.这个问题在Python 3.5和Python 2.7(在Anaconda下运行)中体现出来.
我知道绑定方法是通过执行类似操作获得的闭包TestClass.test_method.__get__(instance, type(instance)).不过,我希望这self.sample_method已经是这样一个封闭的引用,使self.sample_method和instance.sample_method代表相同的参考.
令我困惑的部分原因是pytest我正在运行的真实测试的输出(处理公关matplotlib):
assert <bound method TestTransformFormatter.transform1 of <matplotlib.tests.test_ticker.TestTransformFormatter object at 0x7f0101077b70>> is <bound method TestTransformFormatter.transform1 of <matplotlib.tests.test_ticker.TestTransformFormatter object at 0x7f0101077b70>>
E + where <bound method TestTransformFormatter.transform1 of <matplotlib.tests.test_ticker.TestTransformFormatter object at 0x7f0101077b70>> = <matplotlib.ticker.TransformFormatter object at 0x7f0101077e10>.transform
E + and <bound method TestTransformFormatter.transform1 of <matplotlib.tests.test_ticker.TestTransformFormatter object at 0x7f0101077b70>> = <matplotlib.tests.test_ticker.TestTransformFormatter object at 0x7f0101077b70>.transform1
Run Code Online (Sandbox Code Playgroud)
如果我正确理解输出,实际比较(第一行)实际上是比较相同的对象,但不知何故出现了False.在这一点上我唯一可以想象的__get__是,实际上被称为两次,但我既不知道为什么/在哪里/如何,也不知道如何解决它.
它们不是相同的引用 - 表示两种方法的对象占用内存中的不同位置:
>>> class TestClass:
... def sample_method(self):
... pass
... def test_method(self, method_reference):
... print(hex(id(method_reference)))
... print(hex(id(self.sample_method)))
...
>>> instance = TestClass()
>>> instance.test_method(instance.sample_method)
0x7fed0cc561c8
0x7fed0cc4e688
Run Code Online (Sandbox Code Playgroud)
但是,更改为method_reference == self.sample_method将使断言通过.
编辑自问题扩展:似乎是一个有缺陷的测试 - 可能代码的实际功能不需要引用是相同的(is),只是等于(==).因此,除了测试之外,您的更改可能不会破坏任何内容.