是否有Python等效的Java的IdentityHashMap?

时间:2013-06-11 21:23:45

标签: java python object-identity

我正在构建一个数据结构,并希望构建一个dict映射X-> Y,其中X是我正在行走的数据结构中的一个字段,Y是我正在构建的数据结构中的一个字段在飞行中。 X是一种不可用的类型。

4 个答案:

答案 0 :(得分:1)

Java的IdentityHashMap的目的是模拟动态字段。由于Python语言已经直接支持动态属性,因此您不需要地图,只需将Y分配给X的属性

即可
x.someSuchRelation = y;

答案 1 :(得分:1)

中平凡:

idmap = {}
idmap[id(x)] = y

使用id x作为词典键

答案 2 :(得分:0)

如果将不可用对象包装在另一个对象中,则可以使用常规Python dict。具体来说,这样的事情:

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)

然后就像some_dict[Wrapper(unhashable_object)]一样使用它。

这比使用id(o)作为键更有用的方法,如果您之后还需要能够访问对象本身(显然为key.o)。如果你不这样做(并且垃圾收集不是问题),那就使用它。

答案 3 :(得分:0)

通常,对此常见问题给出的无效解决方案是使用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

为避免这种情况,您必须保留每个插入对象的引用。恕我直言,唯一可行的选择是创建新的字典/集合类:

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