Python的秘密生活:Memory中的雕像

发布: (2025年12月17日 GMT+8 10:35)
4 min read
原文: Dev.to

Source: Dev.to

演示字符串的别名

午后的阳光穿透图书馆空气中舞动的尘埃。Timothy 在掌握了 Name Tag 概念后信心十足。他想向 Margaret 展示自己学到的东西。

“看这个,” Timothy 把笔记本电脑转向她说。“我会创建两个标签,greeting_onegreeting_two。它们指向同一个字符串对象。然后我会修改其中一个,证明另一个也会随之改变。”

greeting_one = "Hello"
greeting_two = greeting_one

# Timothy 的计划:通过第二个标签修改对象。
greeting_two += " World"

print(f"greeting_two is: {greeting_two}")
print(f"greeting_one is: {greeting_one}")

Timothy 预期两个变量都会显示 "Hello World"

greeting_two is: Hello World
greeting_one is: Hello

他再次运行代码,得到相同的结果。

“但你说它们是引用!你之前用列表演示过!”

Margaret 解释说,字符串的行为不同于可变容器。

理解字符串的不可变性

Margaret 用一座大理石雕像作比喻:

  • 石头(不可变) – 字符串不能就地修改,就像石像一样。
  • 白板(可变) – 列表可以在不创建新对象的情况下被修改。

她展示了过程:

  1. Python 看到标记为 "Hello" 的原始石块。
  2. 操作 greeting_two += " World" 无法在现有石块上雕刻 " World"
  3. Python 创建一个 新石块,其中包含 "Hello World",并放在新的内存位置。
  4. greeting_two 重新绑定到这个新块,而 greeting_one 仍然指向原来的 "Hello" 块。

因此,+= 操作后,这两个标签不再引用同一个对象。

检查对象 ID

Timothy 想要具体的证据来证明创建了新对象。

s = "Hello"
print(f"Start ID: {id(s)}")

s += " World"
print(f"End ID:   {id(s)}")

典型输出:

Start ID: 2667049832100
End ID:   2667051284300

不同的 ID 证实了 新字符串对象 已被分配。

不可变 vs 可变 类型

类别示例特征
不可变(石头)str, int, float, tuple不能就地改变。+=upper()、切片等操作会创建 新对象(重新绑定)。共享引用是安全的。
可变(白板)list, dict, set可以就地修改。操作会改变原始对象,因此共享引用会看到这些更改。

要点

  • 字符串(以及其他不可变类型)永远不会被修改;任何“修改”都会产生一个 新对象
  • 列表和其他可变容器可以就地改变,所以别名会看到相同的更新。
  • 了解哪些对象是不可变的、哪些是可变的,有助于在共享引用时避免意外的 bug。

下次,Margaret 和 Timothy 将探讨 “真相的秘密生活”——发现即使在 Python 中,空也会是 False

Back to Blog

相关文章

阅读更多 »