Hop*_*Abc 14 python memory dereference
你可以取消引用从idPython函数中检索的变量id 吗?例如:
dereference(id(a)) == a
Run Code Online (Sandbox Code Playgroud)
我想从学术角度来了解; 我知道有更实用的方法.
mar*_*eau 28
这是一个基于"Tiran"在讨论中引用的注释的实用函数,它引用了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
Run Code Online (Sandbox Code Playgroud)
不容易。
您可以遍历gc.get_objects()列表,测试每个对象是否相同,id()但这不是很实用。
该id()函数不可取消引用;它基于内存地址的事实是 CPython 实现细节,其他 Python 实现不遵循。
有几种方法,不难做到:
在 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]
Run Code Online (Sandbox Code Playgroud)
从评论中获得的平均速度更快(感谢@Martijn Pieters):
def deref_fast(id_):
return next(ob for ob in gc.get_objects() if id(ob) == id_)
Run Code Online (Sandbox Code Playgroud)
最快的解决方案来自@martineau 的答案,但确实需要暴露 python 内部结构。上面的解决方案使用标准的 python 结构。
注意:已更新至 Python 3。
\n这是改编自另一条评论的另一个答案,这是“Peter Fein”的评论,在 @Hophat Abc 的讨论中,他在自己对自己问题的回答中引用了这一点。
\n虽然不是一般答案,但在您了解要查找其 id 的对象的类 \xe2\x80\x94 而不是它们是任何id 的情况下可能仍然有用。我觉得即使有这种限制,这也可能是一种有价值的技术(并且没有我的其他答案所存在的安全问题)。基本思想是创建一个跟踪自身实例和子类的类。
\n#!/usr/bin/env python3\nimport weakref\n\nclass MetaInstanceTracker(type):\n """ Metaclass for InstanceTracker. """\n\n def __new__(cls, name, bases, dic):\n cls = super().__new__(cls, name, bases, dic)\n cls.__instances__ = weakref.WeakValueDictionary()\n return cls\n\nclass InstanceTracker(object, metaclass=MetaInstanceTracker):\n """ Base class that tracks instances of its subclasses using weakreferences. """\n\n def __init__(self, *args, **kwargs):\n self.__instances__[id(self)]=self\n super().__init__(*args, **kwargs)\n\n @classmethod\n def find_instance(cls, obj_id):\n return cls.__instances__.get(obj_id, None)\n\n\nif __name__ == \'__main__\':\n\n class MyClass(InstanceTracker):\n def __init__(self, name):\n super(MyClass, self).__init__()\n self.name = name\n def __repr__(self):\n return \'{}({!r})\'.format(self.__class__.__name__, self.name)\n\n obj1 = MyClass(\'Bob\')\n obj2 = MyClass(\'Sue\')\n\n print(MyClass.find_instance(id(obj1))) # -> MyClass(\'Bob\')\n print(MyClass.find_instance(id(obj2))) # -> MyClass(\'Sue\')\n print(MyClass.find_instance(42)) # -> None\n\nRun Code Online (Sandbox Code Playgroud)\n