我需要设计支持某种不确定性的对象(或者如果你愿意,可以使用狂野角色)它的组件。 这项工作是用Python完成的。
考虑以下课程
class C():
def __init__(self, p1):
self.p1 = p1
属性p1
可以是“x”,“y”,“z”,但有时是“x或y”,或任何其他组合。
如果p1
c1
为'x'且p1
c2
为'x或y',则c1 == c2
必须返回True
。通过提供适当的__eq__
功能可以轻松实现这一点。
但是,这些对象也需要存储在集合中,因此我需要提供__hash__
函数。
对于这种情况,您将如何计算哈希函数,例如c1 == c2
然后hash(c1) == hash(c2)
?
不好这就是原因
c1 = C('x')
c2 = C('x or y or z')
c1 == c2 #True
hash(c1) == hash(c2)#False
答案 0 :(得分:1)
您的平等标准不具有传递性,因此无效:
C('x') == C('x or y') == C('y')
但
C('x') != C('y')
由于你可以构造一个等于所有其他C('x or y or z or a or ...')
的元素,唯一满足c1 ==c2⇒hash(c1)== hash(c2)的哈希函数是一个常数,即
def __hash__(self):
return 0
答案 1 :(得分:0)
我刚刚意识到我的设计要求有问题。 C('x')== C('x或y')为True并且C('y')== C('x或y')为True的要求也需要 C('x')== C('y')也将为True。看起来我需要重新思考我的设计,并且可能放弃拥有对象哈希的能力。你觉得怎么样?
答案 2 :(得分:0)
如果
p1
c1
为'x'且p1
c2
为'x或y',则c1 == c2
必须返回True
。
这是非常粗略(即可能很糟糕)的设计。平等应该是可传递的,所以如果c1 == c2
和c2 == c3
,那么c1 == c3
。现在,您的规范要求C('x') == C('x or y')
和C('x or y') == C('y')
,这应该意味着C('x') == C('y')
- 但您可能不希望这是真的。 (而且我看到你在写这篇文章的时候想到了这一点。)
我建议您单独留下__eq__
并使用完全不同的方法来执行这些“模糊”比较,可能类似于is_compatible_with
。或者如果你要重新实现__eq__
,至少要使它符合传递属性的合理性,例如只比较字符串参数。这可能意味着__eq__
对您的特定应用程序不是很有用,但这没关系;这就是为什么你可以创建其他方法。
答案 3 :(得分:0)
最简单的解决方案是让所有对象返回相同的哈希值。这会将集合O(1)性能降低到O(n),因为所包含的对象都将插入到同一个插槽中。然后使用__eq__
方法进行歧视。
关于您的要求,David已经广泛回复了。