python - 具有身份相等性的 Dict 或 WeakKeyDictionary -- 包装不可散列的对象以检查身份
问题描述
我想使用一些对象作为某些 dict 的键,这些对象要么是不可散列的,要么是可散列的,但我想用默认的/ 覆盖它们的 / __eq__
,即iff 。__hash__
object.__eq__
object.__hash__
a == b
a is b
(这些对象可能是numpy.ndarray
,torch.Tensor
或其他东西,但我现在想问一下。)
例如:
x = numpy.array([2,3,4])
d = {x: 5}
那将给出例外TypeError: unhashable type: 'numpy.ndarray'
。
或者:
x = torch.Tensor([2,3,4])
d = weakref.WeakKeyDictionary()
d[x] = 5
print(d[x])
那将给出例外RuntimeError: Boolean value of Tensor with more than one value is ambiguous
。(这是相当误导或出乎意料的。但我认为这是因为它会在bool(__eq__(...))
内部执行。但是,奇怪的是,当我在这里使用法线时没有这样的例外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
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
自己,使用 sth like WrappedRefObject
. 有更好的解决方案吗?这是否已经存在于标准库或其他地方?
解决方案
推荐阅读
- android - 我需要一些方法来访问我的 rpi-4 上的图像以获取我正在制作的 android 应用程序
- html - Angular 应用程序容器更改应用程序大小
- android - Koin 测试 checkModules()
- websocket - 两个 WebSocket STOMP 服务器之间的桥接
- javascript - 为什么重置按钮不适用于加载的图片?
- python - 为什么我在 OneHotEncoding 分类数据时会得到额外的零?
- karate - 如何在空手道机器人中给出位置“C:\Users\V\Downloads\automate.csv”中文件的绝对路径?
- e-commerce - Virtuemart 订单列表
- google-bigquery - BigQuery 长期运行 - ARRAY_AGG
- reactjs - 在引导轮播幻灯片更改上暂停视频