首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解Python中的内存寻址

了解Python中的内存寻址
EN

Stack Overflow用户
提问于 2020-06-26 13:42:10
回答 3查看 166关注 0票数 1

我写这篇文章是为了扩展我对pointersmemory-addressing如何在python中工作的理解。

python是一种高级语言,我了解到内存管理是由Python负责的。

我还了解到,指针可以用id()对象来标识。

假设我有两个变量ab,这两个变量可以用下面的命令交换:

代码语言:javascript
复制
a,b=b,a

使用以下方法可以发现这些变量的identity的变化。

代码语言:javascript
复制
>>> a=2
>>> b=3
>>> id(a)
140732857872688
>>> id(b)
140732857872720
>>> a,b=b,a
>>> a
3
>>> b
2
>>> id(a)
140732857872720
>>> id(b)
140732857872688

正如你所看到的,变量被交换了(正如预期的那样),换句话说,我们可以说分配给idsids被交换了。这在python中是如何发生的?

在另一个例子中,

代码语言:javascript
复制
>>> i=0
>>> id(i)
140732857872624
>>> i+=1
>>> id(i)
140732857872656

1递增i时,如何在幕后创建具有相同名称的新变量(我将其命名为new,因为标识正在更改)?

我又增加了一个例子来进一步扩展我的问题!

操作1:

代码语言:javascript
复制
>>> i,j=0,0
>>> id(i)
140732857872624
>>> id(j)
140732857872624
>>> i,j = i+1,i+1
>>> i
1
>>> j
1
>>> id(i)
140732857872656
>>> id(j)
140732857872656

操作2:

代码语言:javascript
复制
>>> i,j=0,0
>>> i=i+1
>>> j=i+1
>>> i
1
>>> j
2
>>> id(i)
140732857872656
>>> id(j)
140732857872688

当然,操作1和操作2是不同的。这两个操作是如何在低级别上发生的。

一旦已经分配的指针不再被使用,它将如何被重用?如果某个memory-address在某个程序中不能重用,并且每个新操作(在同一个程序中)都必须给出新的memory-address,这是使用高深度recursion时内存溢出的原因吗?

我希望我的问题已经说得很清楚了。

如果我的理解有误,请纠正我。来自机械工程的背景,虽然我已经编程了相当长的一段时间,但这个东西真的让我感到困惑。

问候

EN

回答 3

Stack Overflow用户

发布于 2020-06-26 13:45:36

使用dis查看幕后发生的事情。

代码语言:javascript
复制
In [1]: import dis

In [2]: def swap(): a=1; b=2; a,b=b,a

In [3]: dis.dis(swap)
  1           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)
              4 LOAD_CONST               2 (2)
              6 STORE_FAST               1 (b)
              8 LOAD_FAST                1 (b)
             10 LOAD_FAST                0 (a)
             12 ROT_TWO
             14 STORE_FAST               0 (a)
             16 STORE_FAST               1 (b)
             18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
票数 2
EN

Stack Overflow用户

发布于 2020-06-26 13:52:44

要理解发生了什么,一个简单的心理模型是

  1. Every python变量是一个指针。

即使在Python内部的i=1之后,i也是一个指向包含值1的对象的指针。即使是整数也是普通对象(这在其他语言中并不常见,因为在其他语言中,通常变量最终都会直接包含小整数的值)。

  1. For效率的原因是一些不可变对象被缓存和共享。

小整数被缓存,所以在Python程序中,所有值为0的变量都将是指向同一对象的指针。在第二种情况下,您观察到不同的id,因为值不同(i将指向1,j将指向2)。

请注意,共享仅针对不可变的对象进行,因为除非使用id,否则无法在代码中观察到共享。在Python语言中,这是针对较小的数字和一些较小的字符串(以"interned").结尾的字符串

票数 2
EN

Stack Overflow用户

发布于 2020-08-14 07:08:37

在python中,变量是内存引用。当您创建

代码语言:javascript
复制
a=2

python内存管理器将把这个值2放在内存堆的一个插槽中,并将这个内存插槽的地址分配给变量。本质上

代码语言:javascript
复制
a=adress_of_this_memory_slot

在幕后,每当您调用时,python内存管理器都会查看地址并检索值。

如果对象是不可变的,Python内存管理器会自动重用内存引用。在您的例子中,整数是不可变的对象。所以python按需重用对象,这在python中称为INTERNING

在启动时,python预加载或缓存-5,256范围内的整数的全局列表。只要在这个范围内引用了一个整数,Python就会使用该对象的缓存版本。

因此根据您的第一个示例,您创建了:

代码语言:javascript
复制
a=2
b=3

因此python内存管理器会将这些值添加到两个不同的内存堆插槽中。在您的示例中,它们的地址是:

代码语言:javascript
复制
id(a) ==> 140732857872688 
id(b) ==> 140732857872720

在此之后,任何时候您想要使用int 2,3时,python都会出于优化的目的使用这些内存地址。

用超出这个范围-5,256的整数来尝试你的例子。您将看到python将为这个变量重新创建一个新地址,换句话说,python将不会共享这些值的引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62588690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档