Python 具有in运算符的自定义类奇怪行为集
参加本课程:Python 具有in运算符的自定义类奇怪行为集,python,python-3.x,Python,Python 3.x,参加本课程: class Element(object): __slots__ = ['x', 'y'] def __init__(self, x, y): self.x = x self.y = y @property def pos(self): return (self.x, self.y) def move(self): self.x -= 1 def __hash__(
class Element(object):
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
@property
def pos(self):
return (self.x, self.y)
def move(self):
self.x -= 1
def __hash__(self): return hash(self.pos)
def __eq__(self, x): return (x.pos if isinstance(x, Element) else x) == self.pos
def __ne__(self, x): return (x.pos if isinstance(x, Element) else x) != self.pos
def __repr__(self): return str(self.pos)
现在我将一组元素装入板条箱:
elements = set([Element(i, i) for i in range(10)])
我不明白
print((5, 5) in elements) # True
print(elements)
# {(4, 4), (8, 8), (5, 5), (7, 7), (0, 0), (9, 9), (1, 1), (3, 3), (2, 2), (6, 6)}
for el in elements:
el.move()
print((4, 5) in elements) # False
print(elements)
# {(3, 4), (7, 8), (4, 5), (6, 7), (-1, 0), (8, 9), (0, 1), (2, 3), (1, 2), (5, 6)}
很确定这是因为散列值改变了。(第一个注释下面的段落):如果一个类定义了可变对象并实现了
\uuuuu eq\uuuuu()
方法,那么它不应该实现\uuuuu hash\uuuuuu()
,因为可哈希集合的实现要求键的哈希值是不可变的(如果对象的哈希值发生变化,它将位于错误的哈希桶中). 相当肯定,因此评论,而不是回答:)@shmee这是真的,dict和set需要不可变的键。这就是python的工作原理,没有任何黑客方法可以绕过它。