Python:什么时候两个变量指向同一内存对象?

8

这里有一个例子:

l = [1, 5, 9, 3]
h = l

h[0], h[2] = h[2], h[0]

print(h) # [9, 5, 1, 3]
print(l) # [9, 5, 1, 3]

h = h*2
print(h) # [9, 5, 1, 3, 9, 5, 1, 3]
print(l) # [9, 5, 1, 3]

我的理解是,调用设置h = l将简单地将h指向l指向的同一内存项。那么为什么在最后3行中,hl不会给出相同的结果呢?


1
当您再次将值分配给 h 时,您会更改 h 指向的内容。 - user2357112
这取决于变量的值是否可变。列表是可变的,整数不可变。 - Aran-Fey
h = l 设置会将指针 h 指向 l。但是,将 h = h*2 设置会将指针 h 指向其他位置。 - BrenBarn
7个回答

9
这很简单,运行以下简单测试即可:
l = [1, 5, 9, 3]
h = l

h[0], h[2] = h[2], h[0]

print(h)  # [9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

print id(h), id(l)
h = h * 2
print id(h), id(l)

print(h)  # [9, 5, 1, 3, 9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

如您所见,由于行h = h * 2,h的id已更改。

为什么会这样呢?当您使用*运算符时,它会创建一个新列表(新的内存空间)。在您的情况下,这个新列表被分配给旧的h引用,这就是为什么您可以看到在h = h * 2之后id不同的原因。

如果您想了解更多关于此主题的内容,请确保查看Data Model链接。


5

这个赋值操作确实使得h指向与l相同的项目。但是,它并没有永久地将两者连接起来。当你使用h = h * 2改变h时,你告诉Python在内存中的其他位置构建一个加倍版本,然后让h指向加倍版本。你没有给出任何更改l的指令;那仍然指向原始项目。


4

h = h * 2h 赋值给一个新的列表对象。

你可能希望 原地修改 h

h *= 2
print(h) # [9, 5, 1, 3, 9, 5, 1, 3]
print(l) # [9, 5, 1, 3, 9, 5, 1, 3]

简短明了... h += h * 2 也可以。 :) - l'L'l
那个可以,但是它不会使数字翻倍,而是变成三倍了吧?你的意思是 h += h 吗? - Moses Koledoye
1
是的,谢谢您的纠正,那就是我想说的,我的手机不知怎么把“*2”留在那里了。 - l'L'l

1

每当你给一个变量赋值时,它的身份(内存地址)通常会改变-唯一不改变的原因是你碰巧把它赋了它已经持有的值。所以,你的语句h = h * 2使得h成为一个全新的对象-其值恰好基于先前h的值,但这实际上与它的身份无关。


1

虽然有些棘手,但当你对列表进行乘法运算时,实际上是创建了一个新的列表。

l = [1, 5, 9, 3]
h = l

现在,“l”和“h”引用的是同一内存中的列表。

h[0], h[2] = h[2], h[0]

print(h)  # [9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

你交换了 h 中的值,因此在 l 中的值也发生了变化。当你将它们视为同一对象的不同名称时,这就有意义了。
h = h * 2

print(h)  # [9, 5, 1, 3, 9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

当你将 h * 2 相乘时,你正在创建一个 新的列表,所以现在只有 l 是原始的列表对象。
>>> l = [1, 5, 9, 3]
>>> h = l
>>> id(h) == id(l)
True
>>> id(h)
139753623282464
>>> h = h * 2
>>> id(h) == id(l)
False
>>> id(h)
139753624022264

看看乘法后hid如何改变了?与其他列表操作(如append())不同,*运算符会创建一个新列表,而不是更改当前列表。
>>> h.append(1000)
>>> id(h)
139753623282464    # same as above!

希望这有所帮助!

0
import numpy as np
print np.may_share_memory(l,k)

用于确认变量l和k是否共享同一内存


0

对于任何想了解如何测试两个变量是否实际指向同一个内存地址的人,可以使用is关键字。

对于Python列表,is也适用。或者,对于列表,可以使用元素级别(深入)比较来执行操作,使用==运算符。

下面是一个例子:

>>> j = [1, 2, 3, 456]
>>> i = j
>>> i == j  # element-wise comparison
True
>>> j is i  # both variables point to the same memory address
True
>>> i is j
True

现在我们将i赋值给另一个列表尽管它们具有相同的元素
>>> j = [1, 2, 3, 456]
>>> i = [1, 2, 3, 456]
>>> i == j  # element-wise comparison
True
>>> i is j  # do they point to the same memory address?
False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接