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

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)

  • 段错误,或更糟。例如,现在可能有其他一些对象存在在那里,并且您的程序将默默地与错误的对象一起运行,并因此做出错误的决定,删除您的文件或泄露您的用户数据或加速您的程序应该的带锯控制或更糟。 (6认同)
  • 我见过的最有趣,最危险的代码. (3认同)
  • @NickT:YOLO ;-) (3认同)
  • 但请注意,如果您传递一个无效地址(例如,因为它已被垃圾收集),这将导致解释器出现段错误。 (3认同)
  • @martineau:我认为这不安全,而且肯定不够安全,无法在 Stack Overflow 上发布供人们复制,甚至没有意识到它正在做一些不安全的事情。遍历输入以查找所有 NoIndent 实例而不是尝试通过直接内存访问从 ID 到对象会更好。如果输出中可能出现类似“@@123@@”的字符串而不来自“NoIndent”,则使用 PyObj_FromPtr 会带来崩溃风险和安全问题,即使这种情况不会发生在您身上,这可能发生在任何使用你的答案的人身上。 (2认同)
  • @MarkAmery:如果那是困扰您的问题,您也可以使用“ctypes”来完成(请参阅[answer](/sf/ask/97766791/#15702647))。 (2认同)

Mar*_*ers 8

不容易。

您可以遍历gc.get_objects()列表,测试每个对象是否相同,id()但这不是很实用。

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

  • @Jonathan Vanasco:OP 询问如何根据 id() 而不是名称来查找 _object_ —— 除了有多个之外,它也可以根本没有。 (4认同)
  • 当然,他们有相同的id。这与 OP 问题有什么关系? (3认同)

mun*_*unk 5

有几种方法,不难做到:

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

  • 您现在创建了对*内存中的每个值* 的引用,确保它们不会被垃圾收集。你真的想改用 [`weakref` 模块](http://docs.python.org/2/library/weakref.html#weakref.WeakValueDictionary)。 (3认同)
  • OP是从学术角度提出的,而不是从实际角度提出的。 (2认同)

mar*_*eau 5

注意:已更新至 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\n
Run Code Online (Sandbox Code Playgroud)\n