是否有可能取消引用变量id?

时间:2013-02-21 20:33:22

标签: python memory dereference

你可以取消引用从Python中id函数检索的变量id吗​​?例如:

dereference(id(a)) == a

我想从学术角度来了解;我知道有更实用的方法。

5 个答案:

答案 0 :(得分:24)

这是一个实用函数,基于由“Tiran”在讨论Hophat Abc comment中制作的referenced,它将在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

答案 1 :(得分:3)

不容易。

您可以通过gc.get_objects()列表递归,测试每个对象是否具有相同的id(),但这不是很实用。

id()函数无意可解除引用;它基于内存地址的事实是一个CPython实现细节,其他Python实现不遵循。

答案 2 :(得分:2)

有几种方法,并不难做到:

在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构造。

答案 3 :(得分:2)

di模块有一个C函数,如果对象没有被垃圾回收,你可以这样做:http://www.friday.com/bbum/2007/08/24/python-di/

答案 4 :(得分:1)

这是另一个答案改编自另一个comment,这个由“彼得·费恩”改编,在讨论中,Hophat Abc在他自己对自己的问题的回答中提到了这个问题。

虽然不是一般性答案,但在您了解要查找其ID的对象类的情况下可能仍然有用 - 而不是它们是任何的ID 。基本思想是创建一个跟踪自身实例和子类的类。我觉得即使有这个限制,这也许是一项有价值的技术。

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