python 是否在相等比较中为字符串常量创建一个对象?

mav*_*ick 2 python

在python中进行这样的比较,python是否为字符串常量“help”创建了一个临时对象,然后继续进行相等比较?该对象将在某个时间点后被垃圾回收。

s1 = "nohelp"
if s1 == "help":
   # Blah Blah
Run Code Online (Sandbox Code Playgroud)

PM *_*ing 5

与所有 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)    
Run Code Online (Sandbox Code Playgroud)

运行 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        
Run Code Online (Sandbox Code Playgroud)

请注意,id所有"help"字符串的s都是相同的,除了用b + "elp".
(顺便说一句,Python 会连接相邻的字符串文字,所以"he" + "lp"我可以写"he" "lp", 甚至,而不是写"he""lp")。

直到进程在终止时清理自己之前,字符串文字本身不会被释放,但是b如果超出范围,像这样的字符串将被 GC 处理。

请注意,在 CPython(标准 Python)中,当对象被 GC 处理时,它们的内存将返回给 Python 的分配系统进行回收,而不是操作系统。Python确实会将不需要的内存返回给操作系统,但仅限于特殊情况。请参阅在 Python 中释放内存为什么在 django 中的大型查询(或一系列查询)后内存没有释放到系统?

讨论此主题的另一个问题:Why strings object are cached in python