Python Dict或WeakKeyDictionary与标识相等--包装不易损坏的对象以检查标识
我想使用一些对象作为某些dict的键,这些dict要么是不可损坏的,要么是可哈希的,但我想用默认的Python Dict或WeakKeyDictionary与标识相等--包装不易损坏的对象以检查标识,python,weak-references,Python,Weak References,我想使用一些对象作为某些dict的键,这些dict要么是不可损坏的,要么是可哈希的,但我想用默认的对象覆盖它们的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu (这些对象可以是numpy.ndarray,torch.Tensor,或其他对象,但我现在想大致询问一下。)
对象覆盖它们的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
(这些对象可以是numpy.ndarray
,torch.Tensor
,或其他对象,但我现在想大致询问一下。)
例如:
这将产生异常TypeError:unhabable类型:“numpy.ndarray”
或:
这将导致异常RuntimeError:具有多个值的张量的布尔值是不明确的
。(这是非常误导人或出乎意料的。但我认为这是因为它会在内部执行bool(\uuuueq\uuuuu(…)
。然而,奇怪的是,当我在这里使用一个正常的dict
时,没有这样的例外。为什么?)
我可以编写一个自定义对象包装器来解决这个问题,如:
class WrappedObject:
def __init__(self, orig):
self.orig = orig
def __eq__(self, other):
return object.__eq__(self.orig, other.orig)
def __ne__(self, other):
return object.__ne__(self.orig, other.orig)
def __hash__(self):
return object.__hash__(self.orig)
这将解决第一个案例。现在我可以写:
x = numpy.array([2,3,4])
d = {WrappedObject(x): 5}
print(d[WrappedObject(x)]) # 5
在一些std库中是否有类似于WrappedObject
的东西
id
函数具有类似的行为,尽管它只返回一个int
,并且没有对原始对象的引用。所以对于这个例子,我可以写:
x = numpy.array([2,3,4])
d = {id(x): 5}
print(d[id(x)]) # 5
请注意,这可能有问题!如果x
稍后被释放,那么理论上可以创建另一个具有相同id
的对象,因为id
只保证在其生存期内是唯一的,而不是在其生存期后。
(相关问题,尽管公认的答案确实存在此问题。)
对于WrappedObject
,此问题不会发生,因为引用始终保持活动状态
有没有什么东西可以把dict
自动用WrappedObject
之类的东西包在引擎盖下面?也就是说,我特别希望对于所有密钥,它只使用它们的标识来实现平等
现在考虑我的第二个例子,特别是代码> WeakKeyDictionary < /代码>。我无法使用
WrappedObject
,因为WrappedObject
本身没有保持活动状态,因此所有键都会立即消失:
x = torch.Tensor([2,3,4])
d = weakref.WeakKeyDictionary()
d[WrappedObject(x)] = 5
print(list(d.items())) # prints []
我目前看到的唯一真正的解决方案是自己重新实现WeakKeyDictionary
,使用类似WrappedRefObject
的东西。有更好的解决办法吗?这是否已经存在于std库或其他地方
x = numpy.array([2,3,4])
d = {id(x): 5}
print(d[id(x)]) # 5
x = torch.Tensor([2,3,4])
d = weakref.WeakKeyDictionary()
d[WrappedObject(x)] = 5
print(list(d.items())) # prints []