为什么我们不能使用Python中的地址访问对象?

时间:2013-09-28 10:46:31

标签: python

背景

我最近才知道这是因为垃圾收集会随时清除该位置的内容,所以依赖它会是一个坏主意。可能还有其他一些原因,但我不知道。

我也知道我们可以使用C访问给定位置的对象,因为CPython地址=对象的id。 (我应该感谢IRC人员。)。但我还没试过。

我在谈论这个地址(id):

address = id(object_name)

或者可能是这个(如果有帮助):

hex_address = hex(id(object))

无论如何,我仍然认为如果他们提供一些可以为我做的方法会更好。

我不想在实践中使用这样的方法,但令我困扰的是,我们有一个对象和一些可以给出其地址的东西,但反之亦然。

问题

  • 为什么做出这个决定?
  • 我们可以在Python级别使用疯狂的内省/黑客来做到这一点吗?我被告知我们不能在Python级别那样做,但我只是想确定。

2 个答案:

答案 0 :(得分:8)

最简单的答案是:“因为它不需要,并且在不对变量进行低级访问的情况下维护代码更容易”。

更精细的是你可以用这样的指针做的一切,你也可以用python中的基本引用,或weakreferences(如果你想引用一些对象而不禁止它的垃圾收集)。

关于“黑客”:

  1. 您可以遍历垃圾收集器并取出对象

    import gc
    
    def objects_by_id(id_):
        for obj in gc.get_objects():
            if id(obj) == id_:
                return obj
    
  2. 您可以使用mxtools

    mx.Tools.makeref(id_)
    
  3. 您可以使用ctypes

    ctypes.cast(id_, ctypes.py_object).value
    

答案 1 :(得分:1)

正如我写的elsewhere


id仅定义为当前现有元素中元素的唯一数字。一些Python实现(事实上,除了CPython之外的所有主要实现)都不返回内存地址。

%~> pypy
Python 2.7.3 (480845e6b1dd219d0944e30f62b01da378437c6c, Aug 08 2013, 17:02:19)
[PyPy 2.1.0 with GCC 4.8.1 20130725 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``arguably, everything is a niche''
>>>> a = 1
>>>> b = 2
>>>> c = 3
>>>> id(a)
9L
>>>> id(b)
17L
>>>> id(c)
25L

所以你必须保证它的内存地址。此外,由于此,Python不提供id → object映射,尤其是如果原始文件被删除,id映射到的对象可以更改。

你必须问为什么你持有id。如果是出于空间原因,请记住容器实际上将引用保存到项目中,因此[a, a, a, a, a]实际占用的空间比[id(a), id(a), id(a), id(a), id(a)]; a少。

您还可以考虑为所有相关项目制作dict {id: val}并存储该项目。这将使val保持活动状态,因此您可以使用weakref来允许val被垃圾回收。请记住,use weakref if you want a weakref


所以基本上是因为没有可靠的解决方案,这与平台无关。

  

让我感到困扰的是,我们有一个对象和一些可以提供其地址的东西

然后记住我们。 CPython仅在(正确)假设地址是唯一的情况下优化id。你永远不应该将视为一个地址,因为它没有被定义为。


  

为什么做出这个决定?

因为如果我们要从id访问内容,我们就可以做各种愚蠢的事情,比如访问未经初始化的内容。它还可以通过移动地址来防止解释器优化事物(如果项目必须具有内存地址,则像PyPy这样的JIT编译器不能轻易存在)。此外,无法保证物品在任何时候都是活着的,甚至不是同一物品。

当引用占用的空间少于整数(它是引用+数字对象)时,没有必要只使用引用(或weakref,如果愿意的话),这将始终做正确的事情。