繁体   English   中英

当__eq__未被调用时,为什么我的对象从列表中正确删除?

[英]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)用于比较,并从其文档:

如果o1o2是同一个对象, PyObject_RichCompareBool()将始终返回1Py_EQ0Py_NE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM