通过id()获取对象?
比方说,我有一个Python对象的ID,我通过做id(thing)
检索。 我如何通过我给的身份证号码再次找到thing
?
你可能会考虑以另一种方式来实现它。 你知道weakref模块吗?
(已编辑)Python weakref模块允许您将引用,字典引用和代理保留给对象,而不必在引用计数器中计算这些引用。 他们就像符号链接。
如果对象仍然存在,可以通过ctypes
完成:
import ctypes a = "hello world" print ctypes.cast(id(a), ctypes.py_object).value
输出:
hello world
如果你不知道对象是否仍然存在,这是一个不确定的行为和怪异的崩溃或更糟的配方,所以要小心。
简短的回答,你不能。
很长的答案,你可以维护一个字典ID映射到对象,或通过穷举搜索gc.get_objects()
查找ID,但这会产生两个问题之一:字典的引用将保持对象的活着,并防止GC ,或者(如果它是一个WeakValue字典或者你使用了gc.get_objects()
),这个ID可能会被释放并被重新用于一个完全不同的对象。
基本上,如果你正在试图做到这一点,你可能需要做一些不同的事情。
您可以使用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")
只是提到这个模块的完整性。 Bill Bumgarner编写的这段代码包含一个C扩展,可以在不存在每个对象的情况下循环执行所需的操作。
该函数的代码非常简单。 每个Python对象都由一个指向PyObject
结构的指针来表示 。 因为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; }
如果原始对象不再存在,则结果是未定义的。 它可能会崩溃,但它也可能返回一个新的对象的引用,这个新的对象是旧内存中的位置。
eGenix mxTools库确实提供了这样的功能,虽然标记为“expert-only”: mx.Tools.makeref(id)
这将做到:
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))
但我建议实施一个更体面的方式。