Python 列表 remove 方法:实现原理如何?

0 投票
2 回答
2549 浏览
提问于 2025-04-16 01:44

在Java中,我有一个客户端类,这个类有一个叫“code”的属性,还有一个equals方法。这个equals方法会接收另一个客户端对象,并把它的code属性和自己进行比较。

在Python中,我刚刚了解到有一个__cmp__方法,可以实现和Java的equals方法一样的功能。于是,我也这样做了。我创建了一个客户端类,里面有“code”属性,还有一个comp方法,用来检查code是否相同。

class Client():
    def __init__(self, code):
        self.code = code

    def __cmp__(self, obj):
        return obj.code == self.code

    def __repr__(self):
        return str(self.code)

然后,我把3个Client对象放进了一个Python的列表里:

bla = [Client(1), Client(2), Client(3)]

接着,当我尝试:

bla.remove(Client(3))

结果很神奇,Python把第一个元素(code为1的Client)给删除了。

我到底做错了什么呢?我查找了Python库文件中列表的实现,但不太容易找到。

有没有人能帮帮我?

2 个回答

4

听起来你其实想要用 __eq__ 这个东西。

class Client():
    def __init__(self, code):
        self.code = code

    def __eq__(self, obj):
        return obj.code == self.code

    # this is how you usually write cmp, Amber explained the problem
    def __cmp__(self, other):
        return cmp(self.code, other.code)

    def __repr__(self):
        return str(self.code)

顺便说一下,你的那个有问题的例子里,__cmp__ 返回了 False,这是符合预期的。但是在 Python 里,False == 0,也就是说如果 __cmp__ 返回 0,就表示比较的两个元素是相等的。所以这就是为什么它会把第一个元素去掉的原因!

5

http://docs.python.org/reference/datamodel.html#object.__cmp__

__cmp__(self, other)

当进行比较操作时,如果没有定义丰富的比较方法,就会调用这个方法。这个方法应该返回一个负数,如果 self 小于 other;返回零,如果 self 等于 other;返回一个正数,如果 self 大于 other

基本上,你应该修改你的 __cmp__ 方法实现为...

def __cmp__(self, obj):
    return cmp(obj.code, self.code)

Python 中的 cmp() 内置函数专门设计用来比较两个参数,并返回 __cmp__ 方法应该返回的值。

Python 还有一个不同的函数叫 __eq__,它只检查两个对象是否相等,而你当前的 __cmp__ 实现更适合这个功能。

撰写回答