Python中的字符串駐留

C#中的字符串駐留

熟悉.NET的人都應該知道C#中的字符串駐留機制,.NET維護了一個駐留池,它會把在編譯期間就相同的字符串只保留一份拷貝。如果僅在運行期間值才相同的字符串變量,.NET纔會爲這個2個相同的字符串變量指向同一份引用的。不過.NET提供了一個方法,讓開發人員可以強制將兩個相同的字符串指向同一個引用,使用String類中的Intern方法。

string s1 = "!QAZ2wsx3$%5$$%fe _ ###4@";
string s2 = "!QAZ2wsx3$%5$$%fe _ ###4@";
Console.WriteLine("s1,s2是否引用同一對象:" + object.ReferenceEquals(s1, s2));
string s3 = "bbbbb";
string s4 = string.Concat("bbb", "bbb");
Console.WriteLine("s3,s4是否引用同一對象:" + object.ReferenceEquals(s3, s4));
Console.WriteLine("調用Intern後..." );
s3 = String.Intern(s4);
Console.WriteLine("s3,s4是否引用同一對象:" + object.ReferenceEquals(s3, s4));

如下演示代碼:

clipboard

這樣設計的合理性是因爲string類型在C#中是屬於immutable的,即對string的修改,並不是在原來的內存塊上修改,而是重新開闢一塊新的空間,創建新的對象。

Python的String同樣也有駐留

Python中,同樣爲immutable的String類型,也採用了這種字符串駐留機制。但Python中稍微有點小規則。

1,長度爲0和1的字符串,默認都採用了駐留機制。

>>> a=''

>>> b=''

>>> a is b

True

>>> a='a'

>>> b='b'

>>> a is b

False

>>> a='!'

>>> b='!'

>>> a is b

2.編譯期間就確定了的字符串,也採用駐留機制,但是,僅限於以下這些字符:

"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"

先解釋一下什麼叫做編譯期間,Python是解釋型語言,但是事實上,它的解釋器也可以是理解爲是一種編譯器,它負責將Python代碼翻譯成字節碼,也就是.pyc文件,之後再由Python虛擬機運行。這一點,和.Net的Framework、Java虛擬機很類似。(更多相關內容可以參考《Learning Python》),因此有些代碼會在翻譯成字節碼的時候,就自動的幫程序員預先計算了。

我們可以通過dis方法(分解Python中的字節碼 )來驗證,可以通過python -m dis xxx.py這樣的命令來查看

舉例:如下的一個Python文件test.py

a='abcdef'

b='abc'+'def'

c=''.join(['abc','def'])

print (a,b,c)

print ('a and b are same?',a is b)

print ('a and c are same?',a is c)

運行:

clipboard[1]

可以看到,變量a和b是同一個引用,但是a和c就不是了。再看其字節碼,可以看出,a和b在賦值的時候,就是相同的字符串,但是c就不同了,它是幾個字符串的拼裝,它是在運行期間才知道結果。

注意,必須是字符串必須是在"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"中,不然就不支持字符串駐留。

比如:

>>> a='abcdef!'

>>> b='abcdef!'

>>> a is b

False

3.通過乘法運算符得到的字符串,長度必須小於20。不然也無駐留機制

>>> a='abc'*6                  #長度18

>>> b='abc'*6                  #長度18

>>> a,b

('abcabcabcabcabcabc', 'abcabcabcabcabcabc')

>>> a is b

True

>>> a='abc'*7 #長度21

>>> b='abc'*7 #長度21

>>> a is b

False

這樣的設計目的是爲了保護.pcy文件不會被錯誤代碼搞的過大,例如有人寫了‘abc’*10**10這種代碼。上述代碼也可以通過dis方式看到不同處。

clipboard[2]

4.和C#的字符串一樣,Pyhton也提供intern方法強制2個字符串指向同一個對象,如下代碼:

>>> import sys

>>> a='abcdef!'

>>> b='abcdef!'

>>> a is b

False

>>> a=sys.intern(b)

>>> a is b

True

5.實際上,對於整數數字,Python也會有駐留機制,但是只限於[-5,256]之間的數字。

參考文檔

http://guilload.com/python-string-interning/

http://www.laurentluce.com/posts/python-string-objects-implementation/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章