Возможно ли разделить переменные id?

Можете ли вы разыменовать идентификатор переменной, полученный из функции id в Python? Например:

dereference(id(a)) == a

Я хочу знать с академической точки зрения; Я понимаю, что есть более практичные методы.

Ответ 1

Здесь функция полезности, основанная на comment, сделанная "Тираном" в обсуждении Hophat Abc ссылка, которая будет работать как на Python 2, так и на 3:

import _ctypes

def di(obj_id):
    """ Inverse of id() function. """
    return _ctypes.PyObj_FromPtr(obj_id)

if __name__ == '__main__':
    a = 42
    b = 'answer'
    print(di(id(a)))  # -> 42
    print(di(id(b)))  # -> answer

Ответ 2

Не легко.

Вы можете пройти через gc.get_objects() список, проверяя каждый объект, если он имеет тот же id(), но это не очень практично.

Функция id() не предназначена для разыскания; тот факт, что он основан на адресе памяти, является детальностью реализации CPython, что другие реализации Python не следуют.

Ответ 3

Существует несколько способов, и это не сложно:

В O (n)

In [1]: def deref(id_):
   ....:     f = {id(x):x for x in gc.get_objects()}
   ....:     return f[id_]

In [2]: foo = [1,2,3]

In [3]: bar = id(foo)

In [4]: deref(bar)
Out[4]: [1, 2, 3]

Более быстрый способ в среднем, из комментариев (спасибо @Martijn Pieters):

def deref_fast(id_):
    return next(ob for ob in gc.get_objects() if id(ob) == id_)

Самое быстрое решение находится в ответе от @martineau, но требуется подвергать внутренности python. В приведенных выше решениях используются стандартные конструкции python.

Ответ 5

Здесь еще один ответ, адаптированный из еще одного comment, этот "Петр Фейн" в обсуждении Hophat Abc упоминается в его собственный ответ на его собственный вопрос.

Хотя это не общий ответ, но может быть полезен в тех случаях, когда вы знаете что-то о классе объектов, идентификаторы которых вы хотите искать, в отличие от них, являющихся идентификаторами чего-либо. Основная идея - создать класс, который отслеживает экземпляры и подклассы. Я чувствовал, что это может быть целесообразной техникой даже с этим ограничением.

import weakref

class InstanceTracker(object):
    """ base class that tracks instances of its subclasses using weakreferences """
    class __metaclass__(type):
        """ Metaclass for InstanceTracker """
        def __new__(cls, name, bases, dic):
            cls = super(cls, cls).__new__(cls, name, bases, dic)
            cls.__instances__ = weakref.WeakValueDictionary()
            return cls

    def __init__(self, *args, **kwargs):
        self.__instances__[id(self)]=self
        super(InstanceTracker, self).__init__(*args, **kwargs)

    @classmethod
    def find_instance(cls, obj_id):
        return cls.__instances__.get(obj_id, None)

if __name__ == '__main__':
    class MyClass(InstanceTracker):
        def __init__(self, name):
            super(MyClass, self).__init__()
            self.name = name
        def __repr__(self):
            return '{}({!r})'.format(self.__class__.__name__, self.name)

    obj1 = MyClass('Bob')
    obj2 = MyClass('Sue')

    print MyClass.find_instance(id(obj1))
    print MyClass.find_instance(id(obj2))
    print MyClass.find_instance(42)

Вывод:

MyClass('Bob')
MyClass('Sue')
None