Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有与Java';什么是身份地图?_Java_Python_Object Identity - Fatal编程技术网

是否有与Java';什么是身份地图?

是否有与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作为字典键如果将不可损坏的对象包装到另一个对象中,则可以使

我正在遍历一个数据结构,想构建一个dict映射X->Y,其中X是我正在遍历的数据结构中的一个字段,Y是我正在动态构建的数据结构中的一个字段。X是一种不可损坏的类型。

Java的IdentityHashMap的目的是模拟动态字段。由于Python语言已经直接支持动态属性,所以不需要映射,只需将Y指定给X的属性即可

x.someSuchRelation = y;
琐碎地:

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

使用
x
id
作为字典键

如果将不可损坏的对象包装到另一个对象中,则可以使用常规的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)
然后像
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的大小可能小于指针的大小。