Получить объект по id()?

Скажем, у меня есть идентификатор объекта Python, который я получил, выполнив id(thing). Как найти thing снова по идентификационному номеру, который мне дал?

Ответ 1

Вы, вероятно, захотите рассмотреть возможность его реализации по-другому. Знаете ли вы о модуле weakref?

(Отредактировано) Python модуль weakref позволяет сохранять ссылки, словарные ссылки и прокси-объекты на объекты, не указав эти ссылки в контрольном счетчике, Они похожи на символические ссылки.

Ответ 2

Если объект все еще существует, это можно сделать с помощью ctypes:

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

выход:

hello world

Если вы не знаете, остается ли объект там, это рецепт поведения undefined и странных сбоев или хуже, поэтому будьте осторожны.

Ответ 3

Короткий ответ, вы не можете.

Длинный ответ, вы можете поддерживать идентификатор для сопоставления идентификаторов объектам или искать идентификатор по исчерпывающему поиску gc.get_objects(), но это создаст одну из двух проблем: либо ссылка на dict сохранит объект в живых и предотвратит GC, или (если это WeakValue dict или вы используете gc.get_objects()), идентификатор может быть освобожден и повторно использован для совершенно другого объекта.

В принципе, если вы пытаетесь это сделать, вам, вероятно, нужно сделать что-то по-другому.

Ответ 4

Вы можете использовать модуль 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

Просто отметим этот модуль для полноты. Этот код Билла Бумгарнера включает расширение C, чтобы делать то, что вы хотите, без цикла по всему существующему объекту.

Код для функции довольно прост. Каждый объект Python представлен в C указателем на a PyObject struct. Поскольку id(x) является только адресом памяти этой структуры, мы можем получить объект Python, рассматривая x как указатель на 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;
}

Если исходный объект больше не существует, результатом будет undefined. Это может привести к сбою, но оно также может вернуть ссылку на новый объект, который занял место старого в памяти.

Ответ 6

Библиотека eGenix mxTools предоставляет такую ​​функцию, хотя помечена как "только эксперт": mx.Tools.makeref(id)

Ответ 7

Это сделает:

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

Но я предлагаю реализовать более достойный способ.