python的可變類型與不可變類型


  首先,我們需要知道在python中哪些是可變數據類型,哪些是不可變數據類型。可變數據類型:列表list和字典dict;不可變數據類型:整型int、浮點型float、字符串型string和元組tuple。

  用一句話來概括上述過程就是:“python中的不可變數據類型,不允許變量的值原地發生變化,如果改變了變量的值,相當於是新建了一個對象,而對於相同的值的對象,在內存中則只有一個對象,內部會有一個引用計數來記錄有多少個變量引用這個對象;可變數據類型,允許變量的值原地發生變化,即如果對變量進行append、+=等這種操作后,只是改變了變量的值,而不會新建一個對象,變量引用的對象的地址也不會變化,不過對於相同的值的不同對象,在內存中則會存在不同的對象,即每個對象都有自己的地址,相當於內存中對於同值的對象保存了多份,這里不存在引用計數,是實實在在的對象。

  不可變類型以int為例:

>>> x=1
>>> id(x)
1431399904
>>> y=2
>>> id(y)
1431399936
>>> z=3
>>> id(z)
1431399968
>>> x=x+1
>>> id(x)
1431399936
>>> x+=1
>>> id(x)
1431399968

  這里值得一提的是當x的值變化時,x引用的數據的內存地址發生了變化,換而言之,x引用了其他的數據,而不是在原來的內存地址上將1的引用計數置為0,然后回收內存地址改為1。python的不可變數據類型會開辟一塊新的地址空間存儲一個新的數據,然后將變量名指向新的地址。在我們這里的test中又不得不提到一個python的小數池概念。

>>> m=1234
>>> n=1235
>>> id(m)
2197878893424
>>> id(n)
2197878893392
>>> m=m+1
>>> id(m)
2197878893296
>>> o=n
>>> id(o)
2197878893392

  當x值加1以后x與y等值,此時x與y的值均指向同一個內存地址,那么x並沒有開辟新的內存空間,這與我們之前說的python的不可變數據類型的方式是不相同的,其實python中為了減少開辟內存造成的時間開銷,對於三位內的整型數字類型數據,在開辟一塊內存空間后,后面的三位內的整型數據都放到這個內存空間中,所以三位以內的整型數字類型的id值都是相同的。

  引用計數

  此時m的值由1234變為1235,原先的1234的引用計數變為一,等待python的垃圾清理機制回收內存地址。此時的內存中m與n的值相等,但是他們的內存指向的是不同的地址空間,此時各自的數據引用計數為1,將新變量o也指向n,那么此時n對應的數據的引用計數+1。

  可變數據類型以列表為例:

>>> x=[1,2,3]
>>> y=[1,2,3,4]
>>> id(x)
1665579614408
>>> x.append(4)
>>> x
[1, 2, 3, 4]
>>> id(x)
1665579614408
>>> x=x+[5]
>>> x
[1, 2, 3, 4, 5]
>>> id(x)
1665579617992
>>> x+=[6]
>>> x
[1, 2, 3, 4, 5, 6]
>>> id(x)
1665579617992
>>> x.extend([7])
>>> x
[1, 2, 3, 4, 5, 6, 7]
>>> id(x)
1665579617992
>>> id(y)
1665579615240

  可以看出,只有x=x+n的時候x的內存地址發生了變化,此時為將兩個列表組合成一個新的列表對象。列表本身是在原來的內存地址上修改值。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM