Python中的集减法

Python中的集减法,python,python-2.7,Python,Python 2.7,在我的Python代码中,我有这样一个类: class _Point2D: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return 'point: (' + str(self.x) + ', ' + str(self.y) + ')' 有两个列表,initialPointsList和burnedPointsList: init

在我的Python代码中,我有这样一个类:

class _Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y    

    def __repr__(self):
        return 'point: (' + str(self.x) + ', ' + str(self.y) + ')' 
有两个列表,
initialPointsList
burnedPointsList

initialPointsList = []
initialPointsList.append(_Point2D(1, 1))
initialPointsList.append(_Point2D(1, 2))
initialPointsList.append(_Point2D(1, 3))
initialPointsList.append(_Point2D(1, 4))
initialPointsList.append(_Point2D(1, 5))
initialPointsList.append(_Point2D(1, 6))
initialPointsList.append(_Point2D(1, 7))

burnedPointsList = []
burnedPointsList.append(_Point2D(1, 2))
burnedPointsList.append(_Point2D(1, 3))
我想计算
initialPointsList
burnedPointsList

我已执行:

result = set(initialPointsList) - set(burnedPointsList)
for item in result:
    print item
并获得以下输出:

point: (1, 1)
point: (1, 4)
point: (1, 5)
point: (1, 6)
point: (1, 2)
point: (1, 3)
point: (1, 7)
但我期待另一个结果,没有烧毁的点坐标:

point: (1, 1)
point: (1, 4)
point: (1, 5)
point: (1, 6)
point: (1, 7)

在Python中实现这一点的最佳方法是什么?我的代码有什么不正确的地方?

如果您想让它正常工作,需要定义和特殊方法。如果您定义
\uuuuueq\uuuueq()
,通常也可以定义

\uuuu eq\uuuu()
如果其参数相等(其x和y值相同),则应返回
True
<代码>\uuu ne\uuu()应该做相反的事情。通常,
\uuu eq\uuu()
也需要进行类型检查,如果“其他”值与
self
的类型不同,则返回false

\uuuuu hash\uuuu()
应返回一个数字。对于与
\uuuu eq\uuuu()
相等的两个值,数字应该相同,对于不同的值,数字应该不同,但不是严格要求。一个好的实现是:

def __hash__(self):
    return hash((self.x, self.y))
元组哈希算法将以统计上表现良好的方式组合其元素的哈希值。您有时可能会看到人们在这里推荐按位异或(即
self.x^self.y
),但这不是一个好主意。这种技术丢弃了所有它们共有的位,这导致了较差的散列性能(例如,如果
self.x==self.y
,它总是返回零)


最后,您需要确保在构建对象后,哈希值不会改变。通过将
self.x
self.y
转换为只读,这是最容易实现的。

为了完整起见,下面是凯文回答中提到的
\uuuuueq\uuuuu
\uuuuuuhash\uucode>方法

def __eq__(self, other):
    return type(self) is type(other) and self.x == other.x and self.y == other.y

def __ne__(self, other):
    return not self.__eq__(other)

def __hash__(self):
    return hash((self.x, self.y))
我通过将这些方法添加到类中来测试它,它会生成预期的输出:

point: (1, 5)
point: (1, 6)
point: (1, 1)
point: (1, 4)
point: (1, 7)

cf&&为什么不使用元组而不是类?@dallen:OP可能想做
self.x
而不是
self[0]
。如果这是唯一的原因,那么他们确实应该使用
collections.namedtuple
来避免手工编写类。您不想只测试
其他
。我建议测试
type(self)是type(other)
,因为我们只想为完全相同类型的对象返回相等值(否则,您可以使用
self==other而不是other==self
)。请注意,
type(None)
是合法的,并返回一个合理的唯一值。谢谢Kevin,我更新了我的答案。另外,这只是一种很好的技术,我可能需要更新自己的一些代码。