字符串字面量与所有 Python 常量一样,是在编译期间创建的,此时源代码被转换为字节码。并且因为所有 Python 字符串都是不可变的,所以如果它在多个地方遇到相同的字符串文字,解释器可以重用相同的字符串对象。如果文字字符串是通过文字连接创建的,它甚至可以做到这一点,但如果字符串是通过将字符串文字连接到现有字符串对象来构建的,则不能。
这是一个简短的演示,它在函数内部和外部创建了一些相同的字符串。它还转储其中一个函数的反汇编字节码。
from __future__ import print_function
from dis import dis
def f1(s):
a = "help"
print('f1', id(s), id(a))
return s > a
def f2(s):
a = "help"
print('f2', id(s), id(a))
return s > a
a = "help"
print(id(a))
print(f1("he" + "lp"))
b = "h"
print(f2(b + "elp"))
print("\nf1")
dis(f1)
典型输出在运行 Python 2.6.6 的 32 位机器上
3073880672
f1 3073880672 3073880672
False
f2 3073636576 3073880672
False
f1
26 0 LOAD_CONST 1 ('help')
3 STORE_FAST 1 (a)
27 6 LOAD_GLOBAL 0 (print)
9 LOAD_CONST 2 ('f1')
12 LOAD_GLOBAL 1 (id)
15 LOAD_FAST 0 (s)
18 CALL_FUNCTION 1
21 LOAD_GLOBAL 1 (id)
24 LOAD_FAST 1 (a)
27 CALL_FUNCTION 1
30 CALL_FUNCTION 3
33 POP_TOP
28 34 LOAD_FAST 0 (s)
37 LOAD_FAST 1 (a)
40 COMPARE_OP 4 (>)
43 RETURN_VALUE
请注意,所有"help" 字符串的ids 是相同的,除了使用b + "elp" 构造的字符串。
(顺便说一句,Python 将连接相邻的字符串文字,所以我可以写 "he" "lp",甚至是 "he""lp",而不是写 "he" + "lp")。
在进程在终止时自行清理之前,字符串文字本身不会被释放,但是如果像b 这样的字符串超出范围,则会被 GC'ed。
请注意,在 CPython(标准 Python)中,当对象被 GC'ed 时,它们的内存将返回给 Python 的分配系统以进行回收,不返回给操作系统。 Python 确实将不需要的内存返回给操作系统,但仅在特殊情况下。见Releasing memory in Python和Why doesn't memory get released to system after large queries (or series of queries) in django?
另一个讨论这个话题的问题:Why strings object are cached in python