通过id()获取对象?

Ram*_*hum 114 python

假设我有一个Python对象的id,我通过这个来检索它id(thing).如何thing通过我给出的身份证号码再次找到?

HYR*_*YRY 163

如果对象仍在那里,可以通过以下方式完成ctypes:

import ctypes
a = "hello world"
print ctypes.cast(id(a), ctypes.py_object).value
Run Code Online (Sandbox Code Playgroud)

输出:

hello world
Run Code Online (Sandbox Code Playgroud)

如果您不知道对象是否仍然存在,这是未定义行为的配方和奇怪的崩溃或更糟,所以要小心.

  • 无论如何,今天在CPython中.:^) (13认同)
  • @HamidFzM不,不是真的.如果我有一个ID,我可能甚至不知道该对象是否仍然存在. (9认同)
  • 这个是一个完美的答案! (6认同)
  • 有没有办法在执行此操作之前先检查内存地址是否存在?如果你传递了一个无效的值(比如说,因为它被垃圾收集了),解释器就会出现段错误。 (3认同)
  • `repr`输出id(a)的十六进制表示,为了使用ctypes,必须使用`int(hexid,0)`将其转换回十进制.这是我的两分钱 (2认同)

Man*_*ron 36

您可以使用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")
Run Code Online (Sandbox Code Playgroud)

  • 只要您保持对对象的引用,就不会发生这种情况.同样,这通常是一个坏主意. (9认同)
  • 这具有别名问题:在过去的任意点处获得的ID现在可以引用不同的对象. (8认同)

cha*_*aos 35

Short answer, you can't.

Long answer, you can maintain a dict for mapping IDs to objects, or look the ID up by exhaustive search of gc.get_objects(), but this will create one of two problems: either the dict's reference will keep the object alive and prevent GC, or (if it's a WeakValue dict or you use gc.get_objects()) the ID may be deallocated and reused for a completely different object.

Basically, if you're trying to do this, you probably need to do something differently.

  • +1:同意:不要这样做.只需用正确的键创建一个合适的对象字典 - 你会更开心. (7认同)

Ken*_*der 33

您可能想要考虑以另一种方式实现它.你知道weakref模块吗?

(已编辑)Python weakref模块允许您保留对象的引用,字典引用和代理,而不必在引用计数器中计算这些引用.它们就像是象征性的联系.

  • 有时您无法创建对象的弱引用,例如:TypeError:无法创建对'lxml.etree._Element'对象的弱引用 (5认同)

Unk*_*own 9

只需提及此模块即可完成.Bill Bumgarner编写的这段代码包含一个C扩展,可以在不存在每个对象的情况下执行您想要的操作.

该函数的代码非常简单.每个Python对象是用C由一个指向表示一个PyObject结构.因为id(x)它只是这个结构的内存地址,所以我们可以通过将其x视为指向a的指针来检索Python对象PyObject,然后调用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;
}
Run Code Online (Sandbox Code Playgroud)

如果原始对象不再存在,则结果未定义.它可能会崩溃,但它也可能返回对新对象的引用,该对象在内存中占用旧对象的位置.