我正在尝试编写一个测试,检查包含类的绑定方法的变量是否与对该方法的另一个引用相同。通常这不是问题,但是在同一类的另一个方法中完成时似乎不起作用。这是一个最小的示例:
class TestClass: def sample_method(self): pass def test_method(self, method_reference): print(method_reference is self.sample_method)
我实际上使用的是assert而不是print,但是因为最终结果是相同的,所以这既不在这里也不在那里。测试运行如下:
assert
print
instance = TestClass() instance.test_method(instance.sample_method)
结果是,False即使我期望是这样True。该问题在Python 3.5和Python 2.7(在Anaconda下运行)中均得到体现。
False
True
我知道绑定方法是通过执行类似操作获得的闭包TestClass.test_method.__get__(instance, type(instance))。但是,我希望self.sample_method已经是对这种闭包的引用,因此self.sample_method和instance.sample_method表示相同的引用。
TestClass.test_method.__get__(instance, type(instance))
self.sample_method
instance.sample_method
让我感到困惑的部分原因是pytest我正在运行的真实测试的输出(在上为PR工作matplotlib):
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
如果我正确理解了输出,则实际比较(第一行)实际上是在比较相同的对象,但是不知何故出现了False。在这一点上,我唯一能想到的__get__就是实际上被两次调用,但是我既不知道为什么/在哪里/如何,也不知道如何解决它。
__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
更改为method_reference == self.sample_method将使断言通过。
method_reference == self.sample_method
自问题扩展以来的编辑:似乎是一个有缺陷的测试- 代码的实际功能可能不需要引用相同(is),而是相等(==)。因此,除了测试之外,您所做的更改可能不会破坏任何其他内容。
is
==