如今有幾種不同的 Python 解釋器,包括 CPython、Jython、IronPython 等。我們現(xiàn)在討論的優(yōu)化技術(shù)是跟 CPython 這種標(biāo)準(zhǔn)的 Python 解釋器有關(guān)的。
駐留機(jī)制
Interning(駐留機(jī)制)是指根據(jù)需要重用對象 ,而不是創(chuàng)建新對象。我們通過一些例子來理解 Integer 類型對象和 String 類型對象的駐留機(jī)制。
is - is 是一種運(yùn)算符,用于比較兩個(gè) Python 對象的內(nèi)存位置。
id - id 用于獲取對象的十進(jìn)制形式的內(nèi)存位置。
Integer 對象的駐留
Python 啟動之時(shí)在內(nèi)存中預(yù)加載了一系列 Integer 對象,這些對象是從 -5 到 256 之間的數(shù)字。我們無論何時(shí)創(chuàng)建的該范圍內(nèi)的 Integer 對象都會自動指向這些預(yù)先加載的內(nèi)存位置,Python 不會因此創(chuàng)建新的對象。
使用這樣的優(yōu)化策略的原因很簡單,是由于 -5 到 256 范圍內(nèi)的數(shù)字經(jīng)常會用到。把它們預(yù)存在內(nèi)存中是有實(shí)際意義的。所以,Python 在啟動之時(shí)把它們預(yù)加載到內(nèi)存里面使得運(yùn)行速度和內(nèi)存得到優(yōu)化。
例 1
本例中,變量 a 和變量 b 都被賦值 100。由于 100 是 -5 到 256 范圍內(nèi)的數(shù)值,Python 會使用駐留的對象,變量 b 也會指向同一內(nèi)存位置,而不會創(chuàng)建另一個(gè)值為 100 的對象。
從下面的代碼可以看出,變量 a 和變量 b 指向的是內(nèi)存中同一對象。Python 不會為變量 b 創(chuàng)建新的對象,而是指向了變量 a 的內(nèi)存位置。這是由于 Integer 對象的駐留機(jī)制決定的。
例 2
本例中,變量 a 和變量 b 都被賦值 1000。由于 1000 不在 -5 到 256 范圍內(nèi),Python 會創(chuàng)建兩個(gè) Integer 對象。所以變量 a 和變量 b 的存儲位置就不一樣了。
從下面的代碼可以看出,變量 a 和變量 b 在內(nèi)存中的存儲位置是不同的。
String 對象的駐留
跟 Integer 對象一樣,某些 String 對象也是駐留的。一般來說,任何符合標(biāo)識符命名規(guī)范的 String 對象都是駐留的。有時(shí)也存在例外,所以不要完全依賴于駐留機(jī)制。
例 1
字符串 “Data” 是合法的標(biāo)識符,它會駐留,所以兩個(gè)變量都指向同一內(nèi)存位置。
例 2
字符串 “Data Science” 不是合法的標(biāo)識符,駐留機(jī)制無效,所以兩個(gè)變量指向不同的內(nèi)存位置。
上述例子都來自 Google Colab,使用的 Python 版本是 3.6.9。
在 Python 3.6 中,所有合法的、長度不大于 20 的字符串都是駐留的。但在 Python 3.7 中,長度上限變?yōu)?4096。所以正如我以前提到的,這些標(biāo)準(zhǔn)因 Python 版本而異。
由于不是所有的 String 對象都被駐留,Python 提供了強(qiáng)制駐留字符串的方法 sys.intern()。這個(gè)方法除非確實(shí)需要,否則不建議使用。使用方法參考下面的代碼。
String 對象駐留的重要意義
假定在你的應(yīng)用程序中,會頻繁進(jìn)行字符串操作。如果使用 == 運(yùn)算符來比較長度較大的字符串,Python 會一個(gè)個(gè)字符去比較,這顯然是費(fèi)時(shí)的。但如果這些長字符串被駐留,它們就指向了相同的內(nèi)存位置。由于比較內(nèi)存位置的操作會快得多,我們就可以使用 is 運(yùn)算符來進(jìn)行字符串比較。








暫無數(shù)據(jù)