2009-09-08 168 views
83

比方说,我有一个Python对象的id,我通过id(thing)进行检索。我怎么找到thing再次由我给的身份证号码?通过id()获取对象?

+0

我很好奇:你为什么想这样做?你的目标是什么? – 2009-09-09 12:35:58

+1

@Craig McQueen:http:// stackoverflow。com/questions/1400295/python-class-for-pickle-and-copy-persistent-object – 2009-09-10 18:06:57

+0

我无法重新找到这个源,但我认为id()返回的是特定分发需要的东西它是。现在,重新生成的CPython现在可能会返回一个类似于内存的地址,但其他发行版可能会返回不同的对象类型或不是内存指针的整数。如果有一个内置函数通过id()返回的内容来获取对象,那将会很好。尽管其他持久性用例很难想象。同样,尽管*变量,像C似乎是有道理的;我喜欢Python,因为它像大多数其他语言一样缺乏标点欺骗。 – DevPlayer 2015-06-24 02:34:36

回答

26

你可能要考虑实现它的另一种方式。你意识到weakref模块吗?

(编辑)Python weakref module可让您保留对象的引用,字典引用和代理,而不必在引用计数器中计算这些引用。它们就像符号链接。

+4

有时您不能创建对该对象的弱引用,例如:TypeError:无法创建对'lxml.etree._Element'对象的弱引用 – darkk 2011-06-23 09:17:03

32

您可以使用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") 
+5

这有一个别名问题:在过去的任意点获得的ID现在可能引用不同的对象。 – chaos 2009-09-08 22:37:59

+6

只要你保留了对象的引用,就不会发生。同样,这通常是一个坏主意。 – 2009-09-08 23:16:53

+0

我同意许多其他评论者:不要这样做。制作你自己的对象字典。 – 2009-09-09 11:26:23

34

简短的回答,你不能。

很长的答案,你可以保留一个字典,将ID映射到对象,或通过详尽搜索gc.get_objects()来查找ID,但这会产生以下两个问题之一:或者字典的引用会使对象保持活动状态并阻止GC ,或者(如果它是一个WeakValue字典或者您使用gc.get_objects()),该ID可能会被重新分配并重新用于完全不同的对象。

基本上,如果你想要做到这一点,你可能需要做一些不同的事情。

+0

我一直打算抛弃对象的'__del__'中的id引用,你认为这会确保事情不会中断吗? – 2009-09-08 22:44:58

+6

+1:同意:不要这样做。只需用适当的键创建一个适当的对象字典 - 你会更快乐。 – 2009-09-08 23:51:03

+1

@ cool-RR:是的,你应该安全。 – chaos 2009-09-09 12:57:13

7

只是提到这个模块的完整性。 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; 
} 

如果原始对象不再存在,则结果是未定义的。它可能会崩溃,但它也可能返回一个对旧内存中的旧对象的引用。

116

如果对象仍然存在,这可以通过ctypes完成:

import ctypes 
a = "hello world" 
print ctypes.cast(id(a), ctypes.py_object).value 

输出:

hello world 

如果你不知道该对象是否仍然存在,这是一个配方不明确的行为和怪异的崩溃或更糟,所以要小心。

+9

无论如何在今天的CPython中。 :^) – DSM 2013-03-29 14:24:48

+4

这是一个完美的答案! – 2013-11-11 21:44:00

+8

@HamidFzM不,不是真的。如果我有一个ID,我可能甚至不知道该对象是否仍然存在。 – glglgl 2014-07-21 08:13:01

0

这样做:

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)) 

但我建议实施一个更体面的方式。