【问题标题】:Why is python storing these two variables at the same location?为什么 python 将这两个变量存储在同一位置?
【发布时间】:2020-10-29 04:50:39
【问题描述】:

考虑以下代码:

x = 50000000
y = 50000000

print(hex(id(x)), hex(id(y)))
print(x is y)

这给出了:

0x23ef28ec930 0x23ef28ec930
True

现在我被引导相信对于小的值,python 使用优化来将它们缓存在内存中。 但这个数字明显大于这个值,我认为是 256。

为什么当我声明这些时它们不是单独存储在内存中的?

如果我在打印语句之前添加y+=1 行,那么x and y 将存储在内存中的不同位置,x is yFalse。我原以为它们都是内存中的同一个对象,增加y 也会增加x

很明显,我遗漏了一些基本的东西,希望能得到澄清。

还有一点,这种行为是否取决于变量类型?如果x,y 不是整数而是列表、字符串或任何其他对象怎么办?

谢谢!

【问题讨论】:

  • 它给了我不同的结果。 0x7f907030acf0 0x7f907030a8b0;False你一定做错了什么。
  • @Pygirl 您是否完全按照说明复制了该示例?在 Windows 上以 Python 3.7.7 运行产生与问题相同的结果。
  • @Pygirl:这种行为可能无法以某种方式得到保证。
  • 我在 ubuntu 中试过。 python 3.7.3
  • 我认为这主要是由于 cpython 处理内存寻址的方式。在给出的示例中,两个变量都指向同一个地址,因此is 在比较内存地址时返回True。递增会更改y 指向的值,因此会分配新的内存地址。但是,我不知道在哪些情况下 cpython 解释器会倾向于将不同的内存寻址分配给存储相等值的变量,例如在 @Pygirl 的情况下。

标签: python python-3.x memory memory-management


【解决方案1】:
x = 50000000

在这里,Python 创建一个int 并将其存储在0x23ef28ec930

y = 50000000

在这里,解释器能够以某种方式检测到该数字已经存在于程序中,因此对y 使用了与x 相同的对象。由于这些是数字文字,因此数字 50000000 可能已在编译时存储,然后用于这两个分配。

据我所知,Python 不保证相同的不可变值是否具有相同的地址。你不应该依赖这种行为,除非在处理单例时,如NoneTrueFalse

此外,如果我在打印语句之前添加行 y+=1,那么 x 和 y 将存储在内存中的不同位置,并且 x 是 y 是 False。我会认为由于它们都是内存中的同一个对象,因此递增 y 也会递增 x。

ints 是不可变的。当您执行y += 1 时,您正在为y 分配一个新值,这使得它与x 不同。

还有一点,这种行为是否取决于变量类型?如果 x,y 不是整数而是列表、字符串或任何其他对象怎么办?

这在很大程度上取决于值是可变的还是不可变的。字符串是不可变的,因此相同的字符串可能具有相同的地址。列表是可变的,所以 xy 是指同一个列表还是两个新构建的列表会有很大的不同。这两个 sn-ps 非常不同:

# These have different addresses. They can be changed independently.
x = []
y = []

# These variables refer to the same list.
x = []
y = x

请注意,+= 之类的运算符会尝试更改对象。这对于不可变值显然是不可能的,但是对于列表,y += [6] 修改现有列表,而 y = y + [6] 生成一个新列表。 += 并不总是等同于简单的加法。

【讨论】:

    【解决方案2】:

    python 使用 reference 来提高内存使用效率。因此,python 不是共享相同值并占用内存中两个不同位置的两个变量,而是将其中一个引用到另一个。

    https://docs.python.org/2.0/ext/refcounts.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 2010-12-07
      • 1970-01-01
      • 2012-03-09
      • 2013-04-24
      相关资源
      最近更新 更多