在Python

时间:2015-10-05 13:26:37

标签: 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) + ')' 

有两个列表,initialPointsListburnedPointsList

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))

我想计算initialPointsListburnedPointsList

之间的差异

我执行了:

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中最好的方法是什么?我的代码有什么不对?

2 个答案:

答案 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.xself.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)