Python Dict或WeakKeyDictionary与标识相等--包装不易损坏的对象以检查标识

Python Dict或WeakKeyDictionary与标识相等--包装不易损坏的对象以检查标识,python,weak-references,Python,Weak References,我想使用一些对象作为某些dict的键,这些dict要么是不可损坏的,要么是可哈希的,但我想用默认的对象覆盖它们的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu (这些对象可以是numpy.ndarray,torch.Tensor,或其他对象,但我现在想大致询问一下。)

我想使用一些对象作为某些dict的键,这些dict要么是不可损坏的,要么是可哈希的,但我想用默认的
对象覆盖它们的
\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 []