当前位置:首页>python>Python的字符串驻留机制,内存优化产生的小心思

Python的字符串驻留机制,内存优化产生的小心思

  • 2026-09-10 17:10:06
Python的字符串驻留机制,内存优化产生的小心思

Python的字符串驻留机制,内存优化产生的小心思

介绍一个 python 函数 id(),它接收一个变量为输入,返回其在计算机内存当中的存储地址,例如:

a = "python"
print(id(a))
# Output: 4531959632

(输出结果仅做参考)

然后我们做这样一个实验:定义变量 a 和 b,其同时赋值字符串 "python",再查看它们的地址:

a = "python"
b = "python"
print(id(a), id(b))
# Output: 4519966544 4519966544

结果居然一模一样,这是为什么,明明 a 和 b 是两个变量,却使用了同一地方的内容?

这就引出了我们今天的重点,字符串驻留机制。

定义

Python 会维护一个字符串常量池,当代码中出现重复字符串时,python 不会在新的地方再保存一遍,而是直接找到常量池里对应的内容,让新的变量映射到那里,从而节约内存、提升运行速度。

为什么

因为字符串是一种不可变数据类型,一旦创建存储到某个变量后,就无法修改,改变该变量的内容也只是将该变量所指向的内存地址改变,而不是改变内存里的内容。

不可变数据类型:Python 中的 3 种标准类型 Number(数字),String(字符串),Tuple(元组) 是不可变数据类型。

因此,Python 利用了这一特点,让存储相同字符串的变量共用一块内存地址,就能减少程序的运行开销。

is 和 ==

在 Python 中做 if 判断,我们会遇到两种判断相同的方式 —— is 和 ==。例如:

  • if var is None
  • if var1 == var2

那么为什么会这样呢?

答案:is 和 == 分别有自己的判断规则,而这规则与驻留机制有关系。

符号
规则
理解
==
判断数值内容是否相等
A 和 B 外表
是一样的
is
判断内存地址是否相等
A 和 B 就是
同一个东西

放到语言里,A is B 说的是“A 是 B”,即 A 与 B 是完全相同的,可能会更好理解。

a = "python"
b = "python"
print(a == b, a is b)
# Output: True True

# list 是可变数据类型
c = [1, 2, 3]
d = [1, 2, 3]
print(c == d, c is d)
# Output: True False

由于 list 是可变数据类型,因此尽管其保存的内容相同,但是却因为保存的地址不同而使得 is 判断时为 False。

驻留触发规则

首先要明确一点,并不是所有的字符串都会触发驻留机制!

必然触发的条件

必然触发的条件:

  • 由纯字母、数字、下划线组成的字符串;
  • 无空格、无特殊符号。
a = "python_123"
b = "python_123"
print(a is b)
# Output: True

不会触发的情况

与上面必然触发相反,出现空格、特殊符号等,就不会触发驻留机制:

a = "python 123"
b = "python 123"
print(a is b)
# Output: False

c = "python?"
d = "python?"
print(a is b)
# Output: False

一些 IDE(如 PyCharm)会对代码做额外的优化,使得带空格字符串也能触发驻留机制;但是 Python 原生提供的命令行交互工具是严格遵守触发规则的。

字符串拼接触发的驻留

  • 当字符串的拼接是常量拼接时,代码会在编译过程即被优化,使得驻留机制被触发;
  • 若通过字符串变量拼接的方式,则最终字符串只能在运行过程中产生(因为系统并不知道最终会得到什么结果,无法与现有字符串进行匹配),因此无法触发驻留机制。
a = "pyt" + "hon"
b = "python"
print(a is b)
# Output: True

x = "pyt"
c = x + "hon"
print(c is b)
# Output: False

这也说明了 Python 只对人为事先定义的内容做驻留机制判断。

手动驻留

对于一些特殊情况,例如我们读取的长日志、长文本,因为存在空格、特殊字符,如果让系统自己处理,则可能不触发自动驻留而导致内存浪费。

此时可以用 sys 模块的 sys.intern() 强制驻留:

import sys
s1 = sys.intern("python 123!")
s2 = sys.intern("python 123!")
print(s1 is s2)
# Output: True

整数驻留机制

除了字符串驻留机制,Python 也对一些小整数做了缓存,范围是 [-5, 256] 之间的整数。因为这些小整数是常见、常用的,因此设置驻留可以减少内存开销:

m = 10
n = 10
print(m is n)
# Output: True

x = 300
y = 300
print(x is y)
# Output: False

同样,这套机制会因 IDE 对代码做的额外优化而产生差异,使得当数字变为 300 时依然判断为 True;但是 Python 原生提供的命令行交互工具是严格遵守触发规则的。


往期回顾:

用OpenCV去除图像噪声增强细节 | Part.10

为什么程序员偏爱Dark Mode(深色模式)

dict的增删查改|Python自学成才(番外篇5)

用OpenCV来实现简单的人脸检测 | Part.9

键盘上的Enter键为什么叫“回车”?

最新文章

随机文章