可以解引用变量id吗?

43 投票
4 回答
26989 浏览
提问于 2025-04-17 16:41

你能否解引用一个从Python的 id 函数获取的变量id?比如:

dereference(id(a)) == a

我想从学术的角度了解这个问题;我知道还有其他更实用的方法。

4 个回答

8

有几种方法可以做到这一点,其实并不难:

时间复杂度是 O(n)

In [1]: def deref(id_):
   ....:     f = {id(x):x for x in gc.get_objects()}
   ....:     return f[id_]

In [2]: foo = [1,2,3]

In [3]: bar = id(foo)

In [4]: deref(bar)
Out[4]: [1, 2, 3]

根据评论(感谢 @Martijn Pieters),还有一种平均速度更快的方法:

def deref_fast(id_):
    return next(ob for ob in gc.get_objects() if id(ob) == id_)

最快的解决方案在 @martineau 的回答中,但需要了解一些 Python 的内部机制。上面的解决方案都是用标准的 Python 语法写的。

10

这事儿不太简单。

你可以通过递归的方式遍历 gc.get_objects() 这个列表,逐个检查每个对象是否有相同的 id(),但这样做其实不太实际。

id() 这个函数 并不是为了让你能直接引用;它是基于内存地址的,这只是CPython的一种实现方式,其他的Python实现可能并不这样。

53

这里有一个实用的函数,它是基于“Tiran”在一个博客讨论中(现在已经删除的评论)提到的内容。这个函数可以在Python 2和Python 3中都能使用。

免责声明:如果你去看那个链接的讨论,你会发现有些人认为这个函数太不安全,应该永远不要使用(在下面的一些评论中也提到了这一点)。我并不完全同意这种看法,但我觉得至少应该提到一下关于使用它的争议。

import _ctypes

def di(obj_id):
    """ Inverse of id() function. """
    return _ctypes.PyObj_FromPtr(obj_id)

if __name__ == '__main__':
    a = 42
    b = 'answer'
    print(di(id(a)))  # -> 42
    print(di(id(b)))  # -> answer

撰写回答