程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python之內存池技術

編輯:Python

Python之內存池技術

文章目錄

      • Python之內存池技術
        • 小整數對象
        • 字符串駐留

問題:如果對象頻繁的創建和銷毀, 就會產生很多內存碎片,最終會影響系統的性能。而實際應用中,我們確實在做這樣的操作,尤其是對小整數的使用,

比如1,2,3這些int類型的數據,幾乎每一次使用for循環都會用到它們。即:

  1. 小整數頻繁被使用與銷毀
  2. 頻繁的創建跟銷毀對象將產生內存碎片

小整數對象

python裡提供了對象池技術。int類型數據是不可變對象,這意味著它可以被共享,在python啟動之後,就會在內存中申請一片內存,將頻繁使用的小整數存儲在這裡,在整個程序運行期間,這些小整數都一直存在,不會被銷毀,對它們的使用,僅僅增加了它們的引用計數而已。

那麼有多少整數被緩存了呢?這個范圍其實不大,只有[-5, 257]。當然如果你想擴大這個范圍,你可以選擇修改python源碼來解決。

python交互式解釋器裡來驗證:

>>> a = 12
>>> b = 12
>>> id(a)
140705565998496
>>> id(b)
140705565998496
>>> a = 257
>>> b = 257
>>> id(a)
2389141537712
>>> id(b)
2389141537904

觀察上面的結果,可以發現在緩存范圍內,其內存地址不變,反之,則變。

字符串駐留

對於字符串同樣也是如此。假設有100個變量,都賦值為python,難道真得要在內存當中創建100個對象?為此,python提供了intern機制。簡單來說,python內部維護一個字典(interned),當一個字符串需要駐留時,就去interned中查看這個字符串是否已經存在,如果存在則增加引用計數,不存在的話就增加到字典中。

使用駐留技術,有下面兩個好處:

  1. 節省內存
  2. 字符串比較時,駐留字符串的比較速度遠遠高於非駐留字符串

什麼時候發生駐留

python交互式解釋器裡來驗證會准確些

  1. 編譯時發生駐留,運行時不駐留

    s1 = 'py' + 'thon'
    print(s1 is 'python')
    a = 'py'
    b = 'thon'
    print(a+b is 'python')
    # 輸出結果
    # True
    # False
    

    結果差異原因:s1值是在編譯階段就計算出來的,因此會駐留,而a+b只有在運行階段才會計算,因此沒有發生駐留

  2. 只含大小寫字母、數字、下劃線時發生駐留

    s1 = 'python'
    s2 = 'python'
    print(s1 is s2)
    a1 = 'pyth on'
    b2 = 'pyth on'
    print(a1 is b2)
    # 輸出結果
    # True
    # False
    
  3. 字符串長度為0或1

    空字符串和長度為1的字符串默認都會駐留,python認為這樣的字符串都是經常被使用的字符串

  4. sys.intern指定駐留

    from sys import intern
    s1 = intern('python!')
    s2 = intern('python!')
    print(s1 is s2)
    
  5. 用乘法(*)得到的字符串

    這部分是比較復雜的規則 ,先來看乘數是1的情況:

    1. 字符串只包含下劃線,數字,字母,默認駐留

    2. 字符串長度小於等於1,默認駐留

      >>> s1 = "hello"
      >>> s2 = s1*1
      >>> s1 is s2
      True
      

    如果乘數大於2,規則如下:

    1. 字符串只包含下劃線,數字,字母且長度小於等於20,默認駐留

    2. 含有其它字符時,不論長度是多少,都不駐留

      >>> s1 = "pythonpythonpython"
      >>> s2 = "python"*3
      >>> s1 is s2
      True
      >>> s1 = "&&&"
      >>> s2 = "&" * 3
      >>> s1 is s2
      False
      

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved