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

为什么我们不能用Python中的地址访问对象?,python,Python,背景 我最近才知道,这是因为垃圾收集会在任何时候清除该位置的内容,因此依赖它将是一个坏主意。可能还有其他原因,但我不知道 我还知道我们可以使用C访问给定位置的对象,因为对象的in-CPython address=id。我应该为此感谢IRC的人。。但我还没试过 我说的是这个地址id: address = id(object_name) 如果有帮助的话,也可能是这个: hex_address = hex(id(object)) 不管怎样,我仍然认为如果他们能给我一些方法来帮助我,那会更好 我不想

背景

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

我还知道我们可以使用C访问给定位置的对象,因为对象的in-CPython address=id。我应该为此感谢IRC的人。。但我还没试过

我说的是这个地址id:

address = id(object_name)
如果有帮助的话,也可能是这个:

hex_address = hex(id(object))
不管怎样,我仍然认为如果他们能给我一些方法来帮助我,那会更好

我不想在实践中使用这样的方法,但让我烦恼的是,我们有一个对象和一些东西可以给出它的地址,但没有任何东西可以反过来

问题:

为何作出这个决定? 我们可以在Python级别使用疯狂的内省/破解来实现这一点吗?我被告知我们不能在Python级别这样做,但我只是想确定一下。
最简单的答案是:因为它是不需要的,并且在不需要低级别访问变量的情况下更容易维护代码

更详细一点的是,使用这种指针可以做的所有事情,也可以使用python中的基本引用,或者如果您希望引用某个对象而不禁止其垃圾收集,那么也可以这样做

关于黑客行为:

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

import gc

def objects_by_id(id_):
    for obj in gc.get_objects():
        if id(obj) == id_:
            return obj
你可以用

你可以用

正如我所写的:

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

%~> 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→ 对象映射,尤其是id映射到的对象可以在删除原始对象时更改

您必须询问为什么要保留id。如果是因为空间原因,请记住容器实际上包含对项目的引用,因此[a,a,a,a,a,a]实际上比[ida,ida,ida,ida,ida]占用的空间更少;a

您还可以考虑对所有相关项生成{ID:Val}的DICT,并存储该项。这将使val保持活动状态,因此您可以使用s允许对val进行垃圾收集。记住

所以基本上这是因为没有可靠的独立于平台的解决方案

我很不安,我们有一个物体和一些东西可以给出它的地址

那就记住我们没有。CPython仅在正确假设地址唯一的情况下优化id。您永远不应该将is视为地址,因为它没有定义为

为何作出这个决定

因为如果我们从他们的id访问东西,我们可以做各种愚蠢的事情,比如访问未初始化的东西。它还阻止了解释器通过在JIT编译器周围移动地址来优化事情。如果项目必须有内存地址,像PyPy这样的编译器就不可能那么容易存在。此外,无法保证该项目在任何时候都是活动的,甚至是相同的项目


当引用占用的空间小于一个整数(引用+数值对象)时,不使用引用或weakref(如果愿意)是没有意义的,因为它总是做正确的事情。

您能提供一个需要这样做的场景吗?在一些Python解释器中,id可能会给您地址,但这是一个。地址是什么?我已经用C语言为Python编写了一个标识哈希表,但即使是我,在使用Python的时候也有99%的时间忘记了这些实现细节。如果您在编写Python时脑子里甚至有指针的概念,那么您正在做一些错误的或非常高级和黑客的事情。@马克:几乎在我可能需要的每一个地方,我都有另一种方法来访问对象本身。我使用的是Django消息,我想知道像这样的对象是什么样子的{'messages':}。快速搜索并具有类似的十六进制值表明这将是该对象的位置。所以,我想从./manage.py shell使用该位置访问该对象,为什么他们会给我?然后我发现我不能。我们应该使用id进行身份检查。Python不希望您处理内存地址。在内存中移动对象与JIT编译器无关。这是垃圾收集器关心的问题,如果CPython没有永远与它的C-API结合,它也可以移动内存中的对象。PyPy除了JIT编译之外还有其他特性-我的观点是,当JIT编译的对象得到较低级别的表示时,它自然会有不同的内存地址。跟踪所述地址会增加很多负担,但回报很少。无论哪种方式都很公平。对象不会得到JIT编译。代码得到JIT编译。如果编译后的代码分配了一些obje
它可以证明的ct不会逃逸跟踪,例如,一个临时整数,它避免了分配所有数据。有时,对象的某些部分并非始终保持最新的虚拟化。但在任何情况下,只要代码需要一个地址,对象就被分配并完全更新,或者根本不执行优化。PyPy已经处理了JIT编译器不能很好处理的所有事情。这就是跟踪JIT编译器的美妙之处。@Veedrac:谢谢你的回答:哇!这是一个非常好的答案!非常感谢
ctypes.cast(id_, ctypes.py_object).value
%~> 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