[英]Why is my object properly removed from a list when __eq__ isn't being called?
我有以下代码,这让我抓狂 -
class Element:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def eq(self, other):
print('comparing {} to {} ({})'.format(self.name,
other.name,
self.name == other.name))
return self.name == other.name
Element.__eq__ = eq
elements = [
Element('a'),
Element('b'),
Element('c'),
Element('d')
]
print('before {}'.format(elements))
elements.remove(elements[3])
print('after {}'.format(elements))
产生以下输出 -
before [a, b, c, d]
comparing a to d (False)
comparing b to d (False)
comparing c to d (False)
after [a, b, c]
为什么eq()
输出comparing d to d (True)
?
我正在修补__eq__
而不是简单地在我的Element
类中实现它的原因是因为我正在测试猴子修补如何在我使用其中一个库实现它之前。
第四个元素是与代码传递的对象完全相同的对象( elements[3]
)。
换句话说,
>>> elements[3] is elements[3]
True
>>> elements[3] == elements[3]
True
所以,不需要检查相等性,因为它们(?)是相同的(相同的)。
如果不相同,将进行平等检查。 例如,如果代码传递具有相同值的另一个对象,则将调用__eq__
:
elements.remove(Element('d'))
Python的list.remove()
方法首先检查两个对象是否相同,否则在这种情况list.remove()
退到常规比较方法,如__eq__
。 因此,在这种情况下,由于两个对象都是相同的,因此将从列表中删除。
listremove(PyListObject *self, PyObject *v)
{
Py_ssize_t i;
for (i = 0; i < Py_SIZE(self); i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
...
这里PyObject_RichCompareBool(PyObject *o1, PyObject *o2, int opid)
用于比较,并从其文档:
如果
o1
和o2
是同一个对象,PyObject_RichCompareBool()
将始终返回1
为Py_EQ
和0
为Py_NE
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.