当实现具有多个属性的类时(如下面的玩具示例),处理散列的最佳方法是什么?
我猜__eq__
和__hash__
应该是一致的,但是如何实现一个能够处理所有属性的合适的哈希函数呢?
class AClass:
def __init__(self):
self.a = None
self.b = None
def __eq__(self, other):
return other and self.a == other.a and self.b == other.b
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash((self.a, self.b))
我在this question上读到元组是可哈希的,所以我想知道上面的例子是不是很合理。是吗?
发布于 2010-10-24 02:19:42
对于相等的对象,__hash__
应返回相同的值。它也不应该在对象的生命周期中改变;通常你只为不可变的对象实现它。
一个微不足道的实现就是return 0
。这总是正确的,但性能很差。
您的解决方案,返回一个属性元组的散列,是很好的。但请注意,您不需要在元组中列出在__eq__
中比较的所有属性。如果某些属性对于不相等的对象通常具有相同的值,则将其省略。不要使散列计算比需要的更昂贵。
编辑:一般情况下,我建议不要使用xor来混合哈希。当两个不同的属性具有相同的值时,它们将具有相同的散列,并且使用xor,这些散列将相互抵消。元组使用更复杂的计算来混合哈希,请参见tupleobject.c
中的tuplehash
。
发布于 2012-09-20 19:31:08
写是很危险的
def __eq__(self, other):
return other and self.a == other.a and self.b == other.b
因为如果您的rhs (即other
)对象的计算结果为布尔值False,那么它将永远不会等于任何东西!
此外,您可能希望仔细检查other
是否属于AClass
的类或子类。如果不是这样,您将得到异常AttributeError
或误报(如果另一个类恰好具有同名属性和匹配值)。因此,我建议将__eq__
重写为:
def __eq__(self, other):
return isinstance(other, self.__class__) and self.a == other.a and self.b == other.b
如果您想要一个异常灵活的比较,只要属性按名称匹配,就可以在不相关的类之间进行比较,那么您仍然希望至少避免AttributeError
,并检查other
是否没有任何额外的属性。如何做到这一点取决于具体情况(因为没有标准的方法来查找对象的所有属性)。
https://stackoverflow.com/questions/4005318
复制相似问题