首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Python 字符串驻留機制:為何相同內容字符串 id 有時相同有時不同

     編輯:程式設計綜合問答

Python 對短字符串、標識符形式的字符串會進行 驻留,導致 id() 相同;但動態生成或包含特殊字符的字符串可能不驻留。IDLE 與腳本運行環境優化策略不同,造成觀察差異。

現象重現

# script.py
a = "hello world"
b = "hello world"
print(a is b)  # True (腳本編譯期優化)

# IDLE 交互式
>>> a = "hello world"
>>> b = "hello world"
>>> a is b     # False (交互式逐行編譯,不一定優化)

驻留規則 (CPython 實現細節)

  • 編譯期常量:源代碼中直接出現的字符串字面量,編譯為字節碼時自動驻留。
  • 標識符形式:僅包含字母、數字、下劃線的字符串 (類似變量名)。
  • 長度限制:通常 < 20-40 字符 (實現相關)。
  • 動態生成:+、join、format、讀取輸入等運行時生成的字符串 不驻留。

代碼驗證

# 編譯期常量
a = "hello"
b = "hello"
print(id(a), id(b), a is b)  # 相同 True

# 動態生成
c = "hel" + "lo"
d = "".join(["h","e","l","l","o"])
print(id(a), id(c), a is c)  # 不同 False
print(id(a), id(d), a is d)  # 不同 False

# 強制驻留
import sys
e = sys.intern("hello world!@#")  # 手動驻留
f = sys.intern("hello world!@#")
print(e is f)  # True

IDLE vs 腳本差異原因

  • 腳本:整個模塊一次性編譯,所有字面量在編譯期驻留。
  • IDLE (REPL):逐行編譯執行,每行獨立編譯單元,字面量不跨行驻留 (除非显式 sys.intern)。

實戰建議

  1. 永遠用 == 比較字符串內容,is 僅用於 None、單例、哨兵對象。
  2. 性能敏感場景 (如字典鍵大量重複) 可用 sys.intern() 手動驻留。
  3. 不要依賴驻留行為編寫業務邏輯,它是 CPython 實現細節,非語言規範。

理解驻留機制,避免 is 誤用導致的難以復現 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved