一文掌握Python 的字元串駐留是如何工作的

2025年01月17日06:32:25 科技 1309

一文掌握Python 的字元串駐留是如何工作的 - 天天要聞

Python 是一種靈活的編程語言,它提供了各種機制來優化性能和內存使用情況。其中一種優化技術就是字元串駐留。

字元串駐留

字元串駐留是一個根植於內存和性能優化的概念,尤其是在 Python 等編程語言中。

什麼是字元串駐留?

字元串駐留的核心是只存儲每個不同不可變字元串值的一個副本。不可變字元串一旦創建就無法更改。這種不變性是駐留過程的關鍵,因為它確保存儲的字元串值保持不變,從而允許多個引用安全地指向同一內存位置。

當一個字元串被駐留時,任何其他具有相同值的字元串都將引用相同的內存位置。這意味著 Python 不會為相同的字元串創建新的內存分配,而是重用現有的內存分配。這種重用使字元串駐留成為一種有效的優化技術。

為什麼字元串駐留很有用?

字元串駐留有幾個顯著的好處:

  1. 內存效率:通過僅存儲相同字元串的一個副本,Python 減少了使用的內存量。這對於處理大量重複字元串值的應用程序(例如文本處理、數據解析和日誌系統)尤其有益。
  2. 性能改進:駐留字元串可以加快比較速度。通常,比較兩個字元串需要逐個檢查每個字元,這對於長字元串來說可能非常耗時。但是,如果字元串被駐留,Python 可以簡單地比較它們的內存地址。如果地址相同,則字元串相等。這種指針比較比逐個字元比較快得多。
  3. 一致性和安全性:字元串駐留有助於保持一致性,並避免因擁有同一字元串的多個副本而可能出現的潛在錯誤。由於駐留字元串是不可變的且存儲在單個位置,因此無意中修改一個字元串(如果字元串是可變的)不會影響其他字元串,從而確保數據完整性。

何時應使用字元串駐留?

了解字元串駐留有益的場景可以幫助您做出明智的決定,確定何時在代碼中使用它:

  1. 重複字元串的高頻率:如果您的應用程序涉及處理大量重複字元串,則駐留可以顯著節省內存並提高性能。
  2. 性能關鍵的字元串比較:在字元串比較是性能瓶頸的情況下,實習可以通過利用指針相等性檢查而不是逐個字元的比較來加快比較速度。
  3. 資源受限的環境:在內存受限的環境中,例如嵌入式系統或在有限硬體上運行的應用程序,駐留可以幫助優化內存使用情況。

限制和注意事項

雖然字元串駐留提供了明顯的好處,但重要的是要注意它的局限性:

  • 內存開銷:駐留需要在內存節省和管理駐留字元串池的開銷之間進行權衡。駐留過多的字元串(尤其是較大的字元串)可能會導致駐留字元串池本身的內存使用量增加。
  • 垃圾回收:只要引用了 Interned 字元串,它們通常就不會被垃圾回收。如果 Interned 字元串使用不當,則可能會導致內存泄漏
  • 並非總是自動:Python 不會自動駐留所有字元串。了解何時手動駐留字元串對於實現所需的性能和內存優勢至關重要。

Python 中的字元串駐留是如何工作的

Python 的字元串駐留機制在優化內存使用和提高性能方面起著至關重要的作用。了解 Python 中字元串駐留的工作原理需要探索自動和手動駐留過程,並識別發生駐留的具體場景。

自動駐留

Python 會自動保留某些字元串以優化內存使用和性能。此過程是隱式的,通常涉及類似於標 識符且經常重複使用的字元串。

標識符的駐留

Python 中的標識符(例如變數名和函數名)會自動保留。這些標識符通常由字母數字字元和下劃線組成。Python 之所以保留這些字元串,是因為它們在程序執行過程中被廣泛使用且經常被比較。

示例:標識符的自動駐留

a = 'name'
 b = 'name' 
print (a is b)   # 輸出:True

 x = 'variable_1'
 y = 'variable_1' 
print (x is y)   # 輸出:True

在此示例中,字元串'name''variable_1'由 Python 自動駐留。因此,ab引用相同的內存位置,與x和一樣y

短字元串

Python 還會駐留短字元串,通常是長度少於 20 個字元的字元串。這些短字元串通常會在程序中重複使用,駐留它們可以顯著減少內存使用量。

示例:自動駐留短字元串

a = 'short'
 b = 'short' 
print (a is b)   # 輸出: True

 m = 'longer_string_that_is_not_interned'
 n = 'longer_string_that_is_not_interned' 
print (m is n)   # 輸出: False

在此示例中,短字元串'short'會自動駐留,因此ab引用相同的內存位置。但是,較長的字元串'

longer_string_that_is_not_interned'
不會自動駐留,因此mn引用不同的內存位置。

手動駐留

對於未自動駐留的字元串,Python 提供了一種使用模塊sys.intern()中的函數手動駐留它們的機制sys。當處理較大的字元串或不符合自動駐留標準的字元串時,這很有用。

使用sys.intern()

sys.intern()函數確保相同的字元串共享相同的內存位置,即使它們沒有被 Python 自動駐留。

示例:手動駐留sys.intern()

import sys

a = 'unique_string'
 b = 'unique_string' 
print (a is b)   # 輸出:False

 a = sys.intern( 'unique_string' ) 
b = sys.intern( 'unique_string' ) 
print (a is b)   # 輸出:True

在此示例中,字元串'unique_string'不會自動駐留,因此ab最初引用不同的內存位置。使用之後sys.intern()a和都b引用相同的內存位置,這表明字元串已被手動駐留。

編譯期間駐留

Python 還會在編譯過程中駐留字元串,尤其是那些出現在函數定義和類定義中的字元串。這意味著在編譯時創建的字元串通常會被駐留以優化內存使用並提高性能。

示例:編譯時字元串駐留

defgreet ():return'hello'a = greet()b= 'hello'print ( a is b)   #輸出:True
     



在此示例中,字元串'hello'在函數編譯期間被駐留greet。因此,a和都b引用相同的內存位置。

字元串駐留的含義

字元串駐留會對內存使用和性能產生重大影響。通過了解 Python 何時以及如何駐留字元串,開發人員可以編寫更高效、更優化的代碼。

內存使用情況

通過確保相同的字元串僅存儲一次,駐留字元串可以減少程序的總體內存佔用。這對於處理大量重複字元串值的應用程序尤其有益。

示例:通過 Interning 節省內存

import sys 

str_list = [sys.intern( 'repeat' ) for _ in  range ( 1000 )] 
print (str_list[ 0 ] is str_list[ 999 ])   # 輸出:True

在此示例中,使用sys.intern()確保字元串的所有 1000 個實例都'repeat'引用相同的內存位置,從而節省大量內存。

性能改進

內置字元串允許更快的比較,因為它們啟用了指針相等性檢查,而不是逐個字元的比較。這可以在字元串比較是關鍵操作的應用程序中帶來明顯的性能提升。

示例:使用 Interning 進行更快的字元串比較

a = sys.intern( 'compare_me' ) 
b = sys.intern( 'compare_me' ) 

if a is b: 
    print ( '字元串相同(快速比較)' ) 
else : 
    print ( '字元串不相同' )

a在這個例子中,和之間的比較b很快,因為它涉及檢查它們的內存地址。如果字元串沒有被駐留,比較將涉及檢查每個字元,這會更慢。

字元串駐留髮生的場景

Python 中的字元串駐留並不總是可預測的,但在某些情況下它經常發生。識別這些場景可以幫助您有效利用字元串駐留來優化內存使用和性能。

短字元串和標識符

Python 默認會保留短字元串和標識符。標識符是可用作變數名的字元串,例如字母數字字元串和下劃線。短字元串(通常少於 20 個字元)也會自動保留。

示例:Interned 標識符

a = 'name'
 b = 'name' 
print (a is b)   # 輸出:True

 x = 'name_1'
 y = 'name_1' 
print (x is y)   # 輸出:True

在這些示例中,字元串namename_1被保留,因為它們看起來像標識符,並且由字母數字字元和下劃線組成。因此,ab引用相同的內存位置,就像x和 一樣y

編譯時創建的字元串

在編譯時創建的字元串(例如函數定義中使用的字元串)通常會被駐留。這是因為 Python 將源代碼編譯為位元組碼,在此過程中,某些字元串會被駐留以優化內存使用並提高性能。

示例:編譯時字元串

defgreet ():return'hello'a = greet()b= 'hello'print ( a is b)   #輸出:True
     



hello在此示例中,函數返回的字元串greet在函數編譯期間被駐留。因此,a和都b引用相同的內存位置。

明確駐留sys.intern()

對於未自動駐留的字元串,您可以使用該sys.intern()方法顯式地駐留它們。這對於較長或不符合自動駐留標準但仍在程序中頻繁使用或比較的字元串特別有用。

示例:顯式駐留

導入系統

a = '唯一字元串'
 b = '唯一字元串' 
print (a is b)   # 輸出:False

 a = sys.intern( '唯一字元串' ) 
b = sys.intern( '唯一字元串' ) 
print (a is b)   # 輸出:True

在此示例中,字元串unique string不會自動駐留,因此ab最初引用不同的內存位置。使用之後sys.intern()a和都b引用相同的內存位置,這表明字元串已被手動駐留。

大量字元串

在應用程序處理大量字元串的場景中(例如處理文本數據、解析文件或處理大型數據集),字元串駐留可以顯著節省內存並提高性能。通過駐留重複的字元串,您可以減少總體內存佔用並加快字元串比較操作的速度。

import sys 

words = [ 'interned_word' ] * 1000
 interned_words = [sys.intern(word) for word in words] 

print (interned_words[ 0 ] is interned_words[ 999 ])   # 輸出:True

在此示例中,列表words包含 1000 個字元串實例interned_word。通過使用sys.intern(),字元串的所有實例都將被保留,從而節省大量內存。因此,列表的第一個和最後一個元素interned_words引用相同的內存位置。

緩存和記憶

緩存和記憶技術通常涉及存儲昂貴的函數調用的結果以避免冗餘計算。在這些情況下,字元串駐留可以減少內存使用量並加快緩存字元串的比較速度,從而大有裨益。

示例:使用 Interned 字元串進行緩存

導入系統

緩存 = {} 

def  expensive_function(param):
    param = sys.intern(param)
    如果緩存中的參數:
        返回緩存[param]
    結果= compute_expensive_result(param)
    緩存[param] = result
    返回結果

在此示例中,在檢查緩存之前,expensive_function先實習字元串。這可確保相同的字元串引用相同的內存位置,從而使緩存查找更加高效。param

性能關鍵型應用程序

在性能至關重要的應用程序中,例如那些需要頻繁進行字元串比較或在內存受限的環境中運行的應用程序,字元串駐留可以帶來巨大的好處。通過駐留字元串,您可以優化內存使用率和字元串操作的速度。

示例:性能關鍵型字元串比較

導入系統

a = sys.intern( 'performance' ) 
b = sys.intern( 'performance' )

如果a是b:
    print ( '字元串相同(快速比較)' ) 
else:
    print ( '字元串不相同' )

a在這個例子中,和之間的比較b很快,因為它涉及檢查它們的內存地址。如果字元串沒有被駐留,比較將涉及檢查每個字元,這會更慢。

結論

Python 中的字元串駐留是一種強大的優化技術,通過僅存儲相同的不可變字元串的一個副本來提高內存效率和性能。通過自動駐留標識符和短字元串,Python 可以節省內存並加快字元串比較速度。sys.intern()對於不適用自動駐留的場景,開發人員還可以使用該函數手動駐留字元串。

了解字元串駐留髮生的方式和時間可以幫助您做出明智的決策來優化 Python 代碼,尤其是在處理大量字元串、性能關鍵操作和內存受限環境的應用程序中。通過正確利用字元串駐留,您可以確保您的程序運行得更高效並更好地利用可用資源。

一文掌握Python 的字元串駐留是如何工作的 - 天天要聞

科技分類資訊推薦

上海交大推出本地化部署版DeepSeek,與直接接入有何不同? - 天天要聞

上海交大推出本地化部署版DeepSeek,與直接接入有何不同?

2月17日,上海交通大學迎來了春季新學期開學的第一天。當日,上海交大官方發布消息,推出國內高校首個全國產化、「R1+V3」全系列本地部署的滿血版DeepSeek 671B。上海交大介紹,這是上海交大網路信息中心聯合華為公司技術攻關,基於鯤鵬昇騰科教創新卓越中心的昇騰平台部署,提供交大人專享的千億級大模型服務,開箱即用、...
阿里巴巴北京智能科技公司註銷 - 天天要聞

阿里巴巴北京智能科技公司註銷

天眼查App顯示,近日,阿里巴巴(北京)智能科技有限公司登記狀態由存續變更為註銷。今年1月,該公司已發布簡易註銷公告。該公司成立於2020年9月,法定代表人為包文俊,註冊資本1000萬人民幣,經營範圍包括網路信息、通信、計算機、計算機網路系統工程的技術開發、技術推廣、技術服務等,由阿里巴巴(中國)有限公司全資持...
A股分化和巨震並行 釋放何種信號?科技股行情能否延續? - 天天要聞

A股分化和巨震並行 釋放何種信號?科技股行情能否延續?

上周咱們提到:「港股持續上行下進入去年924行情高位區間,而A股科技股仍有分化下,也需留意市場情緒的回落。」從今日市場表現來看,儘管上周末諸多利好消息密集發布,但港股大幅跳水回落,進而拖累A股早盤走低。加之科技等熱門板塊分化明顯且波動劇烈,市場短期分歧顯著加劇,預計指數在持續上行後,大概率將進入震蕩整理...
全球最大的晶元半導體企業台積電或將收購英特爾20%的股份! - 天天要聞

全球最大的晶元半導體企業台積電或將收購英特爾20%的股份!

有報道稱,世界最大的代工(半導體委託生產)企業台積電可能收購經營困難的美國半導體企業英特爾代工(半導體受託生產)服務(IFS)部門20%的股份。17日,美聯儲援引消息人士的話報道稱,台積電正在考慮根據美國唐納德•特朗普第二屆政府的要求,收購
氪金·硬科技 | 微盟會是中國的AppLovin嗎? - 天天要聞

氪金·硬科技 | 微盟會是中國的AppLovin嗎?

作者 | 耿宸斐編輯 | 宋婉心封面來源 | 公司官網2月12日盤後,去年美股最火科技股AppLovin公布第四季度業績,該公司營收同比增長44%至13.7億美元,超過市場預期的12.6億美元;凈利潤5.99億美元,同比暴增248%。
A股的春天來了? - 天天要聞

A股的春天來了?

中國的股市是一個政策市,也是一個消息市。國際國內,政治經濟,稍有風吹草動,就會影響到A股市場。特別是到了周末,各種正式的非正式的、官方的非官方的消息滿天飛。海量信息令人真假難辨,莫衷一是。春晚上的機器人不過,這兩天倒是有兩則來自正規途徑的消
微信、百度全面接入DeepSeek誰在焦慮?誰在狂歡? - 天天要聞

微信、百度全面接入DeepSeek誰在焦慮?誰在狂歡?

2025 年 2 月 16 號,微信和百度這倆互聯網巨頭,居然同一天宣布全面接入 AI 大模型 DeepSeek!這可太炸裂了,簡直就是改寫 AI 搜索格局的 「王炸」 操作,直接在網上掀起驚濤駭浪,網友們都炸開了鍋,這到底咋回事?