Get object by id()? [duplicate]

╄→尐↘猪︶ㄣ 提交于 2019-11-25 22:47:23

问题


Let\'s say I have an id of a Python object, which I retrieved by doing id(thing). How do I find thing again by the id number I was given?


回答1:


You'll probably want to consider implementing it another way. Are you aware of the weakref module?

(Edited) The Python weakref module lets you keep references, dictionary references, and proxies to objects without having those references count in the reference counter. They're like symbolic links.




回答2:


If the object is still there, this can be done by ctypes:

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

output:

hello world

If you don't know whether the object is still there, this is a recipe for undefined behavior and weird crashes or worse, so be careful.




回答3:


You can use the gc module to get all the objects currently tracked by the Python garbage collector.

import gc

def objects_by_id(id_):
    for obj in gc.get_objects():
        if id(obj) == id_:
            return obj
    raise Exception("No found")



回答4:


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.




回答5:


Just mentioning this module for completeness. This code by Bill Bumgarner includes a C extension to do what you want without looping throughout every object in existence.

The code for the function is quite straightforward. Every Python object is represented in C by a pointer to a PyObject struct. Because id(x) is just the memory address of this struct, we can retrieve the Python object just by treating x as a pointer to a PyObject, then calling Py_INCREF to tell the garbage collector that we're creating a new reference to the object.

static PyObject *
di_di(PyObject *self, PyObject *args)
{
    PyObject *obj;
    if (!PyArg_ParseTuple(args, "l:di", &obj))
        return  NULL;

    Py_INCREF(obj);
    return obj;
}

If the original object no longer exists then the result is undefined. It may crash, but it could also return a reference to a new object that's taken the location of the old one in memory.




回答6:


eGenix mxTools library does provide such a function, although marked as "expert-only": mx.Tools.makeref(id)




回答7:


This will do:

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

But I suggest implementing a more decent way.



来源:https://stackoverflow.com/questions/1396668/get-object-by-id

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!