重新插入集合元素会产生洞
Reinserting set element creates holes
一般来说,如果我们需要将一个对象插入到一个集合中,我们应该使其可哈希(通过实现哈希函数)和可比较(并实现比较函数)。 Set 不提供访问其元素的机制,因此不能直接改变,但可以很容易地绕过。
改变集合项目的一般模式如下
i = next(iter(x))
update(i)
x.add(i)
这似乎适用于几乎所有情况,但出现意外漏洞时除外。
class Foo(object):
def __init__(self, x):
self.x = x
self.count = 0
def __hash__(self):
return hash((self.x, ))
def __iadd__(self, n):
self.count += n
def __eq__(self, other):
return self.x == other.x
>>> x = {Foo(1)}
>>> i = next(iter(x))
>>> i+=1
>>> x.add(i)
>>> x
set([None, <__main__.Foo object at 0x0279D8B0>])
我的猜测是在更新时改变一个 set 元素可能会导致意外行为,但调用 next 只会获取应该不是问题的值(我猜是一个副本)。
知道问题出在哪里吗?
[__iadd__
] should attempt to do the operation in-place (modifying self) and
return the result (which could be, but does not have to be, self)
因此,
def __iadd__(self, n):
self.count += n
return self
然后,
class Foo(object):
def __init__(self, x):
self.x = x
self.count = 0
def __hash__(self):
return hash((self.x, ))
def __iadd__(self, n):
self.count += n
return self
def __eq__(self, other):
return self.x == other.x
x = {Foo(1)}
i = next(iter(x))
i+=1
x.add(i)
print(x)
产量
set([<__main__.Foo object at 0x7f19ae8b9f10>])
您可能想 return 在 iadd 方法中自我。
一般来说,如果我们需要将一个对象插入到一个集合中,我们应该使其可哈希(通过实现哈希函数)和可比较(并实现比较函数)。 Set 不提供访问其元素的机制,因此不能直接改变,但可以很容易地绕过。 改变集合项目的一般模式如下
i = next(iter(x))
update(i)
x.add(i)
这似乎适用于几乎所有情况,但出现意外漏洞时除外。
class Foo(object):
def __init__(self, x):
self.x = x
self.count = 0
def __hash__(self):
return hash((self.x, ))
def __iadd__(self, n):
self.count += n
def __eq__(self, other):
return self.x == other.x
>>> x = {Foo(1)}
>>> i = next(iter(x))
>>> i+=1
>>> x.add(i)
>>> x
set([None, <__main__.Foo object at 0x0279D8B0>])
我的猜测是在更新时改变一个 set 元素可能会导致意外行为,但调用 next 只会获取应该不是问题的值(我猜是一个副本)。
知道问题出在哪里吗?
[
__iadd__
] should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self)
因此,
def __iadd__(self, n):
self.count += n
return self
然后,
class Foo(object):
def __init__(self, x):
self.x = x
self.count = 0
def __hash__(self):
return hash((self.x, ))
def __iadd__(self, n):
self.count += n
return self
def __eq__(self, other):
return self.x == other.x
x = {Foo(1)}
i = next(iter(x))
i+=1
x.add(i)
print(x)
产量
set([<__main__.Foo object at 0x7f19ae8b9f10>])
您可能想 return 在 iadd 方法中自我。