Python: __cmp__ 和测试列表成员

Python: __cmp__ and testing list membership

很抱歉,如果有人已经解决了这个问题,但我找不到答案。

我在为自定义 class 覆盖 __cmp__ 时遇到问题,类似于:

class MyClass(object):
    def __init__(self, prop):
        self.prop = prop
    def __cmp__(self, other):
        return cmp(self.prop, other.prop)

a = MyClass(1)
b = MyClass(2)
c = MyClass(3)
d = MyClass(1)

my_list = [a, b, c]
print a in my_list
print b in my_list
print c in my_list
print d in my_list

# Output:
#
# True
# True
# True
# True

阅读文档告诉我这是预料之中的,因为:

For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.

我的问题有两个:

  • Why does Python (2.7) use == rather than is to test list membership?

因为对于包含检查而言,相等通常比同一性更有趣,尤其是当两个不同的对象可以具有相同的值时。

>>> ('Hello, ' + 'world!') is 'Hello, world!'
False
>>> ('Hello, ' + 'world!') == 'Hello, world!'
True
  • Is there a better way to be doing this, such that I can test whether a specific instance of my class is actually in a container and be able to compare instances based on their attributes?

不是特别的。

列表包含一个等于变量的值,而不是对变量的引用。这样想。这两个代码示例是否相同?是什么让他们与众不同?

class Person:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

# sample one

sam = Person('Sam')
bob = Person('Bob')

people = [sam, bob]

第一个示例是您应该使用 is 关键字的时间。您正在尝试测试列表中的对象是否是列表外的对象,这意味着列表内的 sam 与列表外的 sam 存储在内存中的相同位置。

# sample two

sam = Person('Sam')
bob = Person('Bob')

people = [Person('Sam'), Person('Bob')]

这个示例是您应该使用双等号关键字的时候。您正在尝试测试列表中的对象与列表外的对象相比是否具有值。注意,因为我们用名字 Sam 实例化了不同的人,所以他们的值是相等的,但不是同一个对象。