在我的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中最好的方法是什么?我的代码有什么不对?
答案 0 :(得分:6)
如果您希望此功能正常运行,则需要定义__eq__()
和__hash__()
特殊方法。如果您定义__eq__()
,定义__ne__()
通常也是个好主意。
__eq__()
如果其参数相等(它们的x和y值相同),则应返回True
。 __ne__()
应该反其道而行之。 __eq__()
通常也需要进行类型检查,如果“其他”值与self
的类型不同,则返回false。
__hash__()
应该返回一个数字。对于与__eq__()
相等的两个值,该数字应该相同,并且对于不同的值,它是可取的但不是严格要求它是不同的。一个很好的实现是:
def __hash__(self):
return hash((self.x, self.y))
元组散列算法将以统计上良好的方式组合其元素的散列值。你有时可能会在这里看到人们推荐按位异或(即self.x ^ self.y
),但这不是一个好主意。该技术抛弃了它们共有的所有位,这使得散列性能较差(例如,如果self.x == self.y
,它总是返回零)。
最后,您需要确保哈希值在构造对象后不会更改。通过将self.x
和self.y
转换为只读properties,可以轻松完成此操作。
答案 1 :(得分:2)
为了完整起见,凯文的回答中提到了__eq__
,__ne__
和__hash__
方法。
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)