是否有与Java';什么是身份地图?
我正在遍历一个数据结构,想构建一个dict映射X->Y,其中X是我正在遍历的数据结构中的一个字段,Y是我正在动态构建的数据结构中的一个字段。X是一种不可损坏的类型。Java的IdentityHashMap的目的是模拟动态字段。由于Python语言已经直接支持动态属性,所以不需要映射,只需将Y指定给X的属性即可是否有与Java';什么是身份地图?,java,python,object-identity,Java,Python,Object Identity,我正在遍历一个数据结构,想构建一个dict映射X->Y,其中X是我正在遍历的数据结构中的一个字段,Y是我正在动态构建的数据结构中的一个字段。X是一种不可损坏的类型。Java的IdentityHashMap的目的是模拟动态字段。由于Python语言已经直接支持动态属性,所以不需要映射,只需将Y指定给X的属性即可 x.someSuchRelation = y; 琐碎地: idmap = {} idmap[id(x)] = y 使用x的id作为字典键如果将不可损坏的对象包装到另一个对象中,则可以使
x.someSuchRelation = y;
琐碎地:
idmap = {}
idmap[id(x)] = y
使用
x
的id
作为字典键如果将不可损坏的对象包装到另一个对象中,则可以使用常规的Pythondict
进行此操作。具体来说,是这样的:
class Wrapper(object):
def __init__(self, o):
self.o = o
def __hash__(self):
return id(self.o)
def __eq__(self, o):
return hash(self) == hash(o)
然后像somedict[Wrapper(unhable\u object)]
一样使用它
如果您以后还需要能够访问对象本身(显然是作为
key.o
),那么这是一种比仅使用id(o)
作为键更有用的方法。如果您不这样做(垃圾收集不是问题),就使用它。通常,针对这个常见问题给出的错误解决方案是使用id
。
它被破坏是因为id
仅在现有对象中是唯一的,因此以下情况可能会随机发生:
>>> idmap = {}
>>> idmap[id(x)] = 42
>>> del x
>>> z = SomeObject()
>>> z in idmap
True
不必使用显式的del
语句,只需在函数中向idmap添加一个键即可得到相同的结果:
>>> def add_smthg(idmap):
>>> x = SomeObject()
>>> idmap[id(x)] = 42
>>> idmap = {}
>>> add_smthg(idmap)
>>> z = SomeObject()
>>> z in idmap
True
要避免这种情况,必须保留插入的每个对象的引用。IMHO唯一可行的选择是创建新的词汇/集合类:
class IdentitySet:
def __init__(self, items=None):
if items is None:
items = []
self._identities = {id(item): item for item in items}
def add(self, item):
self._identities[id(item)] = item
def __delitem__(self, item):
del self._identities[id(item)]
def __contains__(self, item):
return id(item) in self._identities
class IdentityDict:
def __init__(self, pairs=None):
if pairs is None:
pairs = []
self._identities = IdentitySet(k for k, _ in pairs)
self._values = {id(k): v for k, v in pairs}
def __getitem__(self, item):
return self._values[id(item)]
def __setitem__(self, item, value):
self._identities.add(item)
self._values[id(item)] = value
def __delitem__(self, item):
del self._identities[item]
del self._values[id(item)]
def __contains__(self, item):
return item in self._identities
并非Python中的所有对象都支持动态属性!这要求您为字段选择一个唯一的名称。如果X不可损坏,那么它可以更改(使映射有点困难)。是否希望“X”实例始终指向“Y”实例?或者你想让这个值的任何X指向那个“Y”吗。如果它是第一个,那么您可以为每个X分配一个id,然后该id应映射到“Y”。如果它是第二个,那么您可以将X临时存储在一个可散列的容器中,例如元组,并将其用作键。我相信可能有更快的方法可以做到这一点(我的蟒蛇有点生锈),但它应该可以工作。@Xonar:很确定你不能散列一个包含未损坏项的元组,是的。(我确实说过我的python已经生锈了:))但是您可以递归地将不可损坏的项添加到元组中。e、 g.将(1,2,[2,3])转换为(1,2,(2,3)),感谢您指出这一点。请注意,对于自定义类,
hash(x)
默认为id(x)
-您会发现在某些情况下,id
在这里是不必要的。请注意,x
必须通过其他地方的引用继续存在,以保证其id
不会被重用。投票被否决,因为@DavisHerring说它被微妙地破坏了,可能会导致随机错误,因为id可以重用。您不应该在哈希相等方面实现相等-py_hash_t的大小可能小于指针的大小。