假设我有一个Python对象的id,我通过id(thing)
检索它。如何通过我给出的身份证号码再次找到thing
?
答案 0 :(得分:146)
如果对象仍然存在,可以通过ctypes
:
import ctypes
a = "hello world"
print ctypes.cast(id(a), ctypes.py_object).value
输出:
hello world
如果您不知道该对象是否仍然存在,这是一个未定义行为的配方和奇怪的崩溃或更糟,所以要小心。
答案 1 :(得分:35)
简短回答,你不能。
答案很长,您可以维护一个用于将ID映射到对象的dict,或者通过穷举搜索gc.get_objects()
查看ID,但这会产生以下两个问题之一:dict的引用会使对象保持活动状态并阻止GC,或者(如果它是WeakValue dict或您使用gc.get_objects()
),ID可能会被释放并重新用于完全不同的对象。
基本上,如果您尝试这样做,您可能需要做一些不同的事情。
答案 2 :(得分:34)
您可以使用gc模块获取Python垃圾收集器当前跟踪的所有对象。
import gc
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
raise Exception("No found")
答案 3 :(得分:30)
您可能想要考虑以另一种方式实施它。你知道weakref模块吗?
(已编辑)Python weakref module允许您保留对象的引用,字典引用和代理,而不必在引用计数器中计算这些引用。它们就像是象征性的联系。
答案 4 :(得分:9)
刚才提到这个模块的完整性。 This code by Bill Bumgarner包含一个C扩展,可以执行您想要的操作,而不会遍历现有的每个对象。
该功能的代码非常简单。每个Python对象都在C中用指向a PyObject
struct的指针表示。因为id(x)
只是这个结构的内存地址,所以我们可以通过将x
视为指向PyObject
的指针来检索Python对象,然后调用Py_INCREF
告诉我们正在创建对象的新引用的垃圾收集器。
static PyObject *
di_di(PyObject *self, PyObject *args)
{
PyObject *obj;
if (!PyArg_ParseTuple(args, "l:di", &obj))
return NULL;
Py_INCREF(obj);
return obj;
}
如果原始对象不再存在,则结果未定义。它可能会崩溃,但它也可能返回对新对象的引用,该对象在内存中占用旧对象的位置。
答案 5 :(得分:3)
eGenix mxTools库确实提供了这样的功能,虽然标记为“仅限专家”:mx.Tools.makeref(id)
答案 6 :(得分:1)
这样做:
a = 0
id_a = id(a)
variables = {**locals(), **globals()}
for var in variables:
exec('var_id=id(%s)'%var)
if var_id == id_a:
exec('the_variable=%s'%var)
print(the_variable)
print(id(the_variable))
但我建议采用更加体面的方式。