Python中的可變與不可變對象

Python中的可變與不可變對象

Python中的全部東西都是一個對象。每一個Python新手都應該學習的是,Python中的全部對象均可以是可變的或不可變的。
圖片描述
讓咱們更深刻地瞭解它的細節...由於Python中的全部東西都是對象,因此每一個變量都包含一個對象實例。當一個對象被初始化時,它被分配一個惟一的對象ID。它的類型是在運行時定義的,一旦設置永遠不會改變,可是若是它是可變類型它的狀態是能夠被改變的。簡單地說,一個可變對象能夠在建立以後被改變,一個不可變對象不能。python

諸如(int,float,bool,str,tuple,unicode)等內置類型的對象是不可變的。像(list,set,dict)這樣的內置類型的對象是可變的。自定義類一般是可變的。要模擬類中的不變性,應該覆蓋屬性設置和刪除以引起異常。

圖片描述

如今出現這個問題,咱們如何肯定咱們的變量是一個可變對象仍是不可變對象。爲此,咱們應該瞭解「ID」和「TYPE」函數的用途。數組

ID和TYPE

內置函數id()以整數形式返回對象的標識。這個整數一般對應於對象在內存中的位置,雖然這是針對Python的實現和正在使用的平臺而言。is運算符用來比較兩個對象的標識。函數

內置函數type()返回一個對象的類型。讓咱們看一個簡單的例子學習

'''示例1''' 
>>> x =「Holberton」 
>>> y =「Holberton」 
>>> id(x)
140135852055856 
>>> id(y)
140135852055856 
>>> print(x is y)' ''比較類型''' 
真的
'''示例2''' 
>>> a = 50 
>>> type(a)
<class:'int'> 
>>> b =「Holberton」 
>>> type(b)
<class:'string'>

如今咱們已經看到了如何比較兩個簡單的字符串變量來找出類型和ID。所以,使用這兩個函數,咱們能夠檢查不一樣類型的對象是如何與變量相關聯以及如何更改對象的。spa

可變和不可變的對象

正如咱們前面所討論的,一個可變對象能夠改變它的狀態或內容,不可變對象不能。code

  • 可變對象
    列表,字典,集,字節數組
  • 不可變對象
    int,float,complex,string,tuple,frozen set [注:set的不可變版本],bytes

一個實用的例子來找出對象類型的可變性對象

x = 10
x = y

咱們正在建立一個int類型的對象。標識符x和y指向同一個對象。圖片

id(x)== id(y)
id(y)== id(10)

若是咱們作一個簡單的操做。內存

x = x + 1

如今unicode

id(x)!= id(y)
id(x)!= id(10)

x被標記的對象被改變。對象10從未被修改過。不可變對象在建立後不容許修改

在可變對象的狀況下

m = list([1,2,3])
n = m

咱們正在建立一個類型列表的對象。標識符m和n被標記爲同一個列表對象,它是3個不可變的int對象的集合。

id(m)== id(n)

如今從列表對象中彈出一個元素確實會改變對象,

m.pop()

對象ID不會被更改

id(m)== id(n)

m和n將在修改後指向同一個列表對象。列表對象如今將包含[1,2]。

那麼從上面的例子中咱們看到了什麼?

Python以不一樣方式處理可變對象和不可變對象。
不可變的訪問比可變對象更快。
當你須要改變對象的大小,例如列表,字典等等時,可變對象是很好用的。當你須要確保你建立的對象始終保持不變時,使用不可變對象。
不可變對象對於「更改」而言基本上是昂貴的,由於這樣作涉及到建立副本。更改可變對象很便宜。

不可變的例外..

並不是全部的不可變對象都是不可變的。

如前所述,Python容器好比元組,是不可變的。這意味着一個tuple的值在建立後沒法更改。可是元組的「值」其實是一系列名稱,它們與對象的綁定是不可改變的。關鍵點是要注意綁定是不可改變的,而不是它們綁定的對象。

讓咱們考慮一個元組t =('holberton',[1,2,3])

上面的元組t包含不一樣數據類型的元素,第一個元素是一個不可變的字符串,第二個元素是一個可變列表。元組自己不可變。即它沒有任何改變其內容的方法。一樣,字符串是不可變的,由於字符串沒有任何可變方法。可是列表對象確實有可變方法,因此能夠改變它。這是一個微妙的點,可是很是重要:不可變對象的「值」 不能改變,但它的組成對象是能作到改變的。

對象如何傳遞給函數

對於咱們來講,瞭解可變類型和不可變類型之間的區別以及將它們傳遞到函數時如何處理是很是重要的。當使用正確的對象時,存儲效率會受到很大影響。

例如,若是一個可變對象在函數中被引用調用,它能夠改變原來的變量自己。所以爲了不這種狀況,須要將原始變量複製到另外一個變量中。不可變的對象能夠經過引用來調用,由於它的值不能被改變。

def updateList(list1):
    list1 + = [10]
n = [5,6] 
print(id(n))#140312184155336
updateList(n)
print(n)#[ 
5,6,10 ] print(id(n))#140312184155336

從上面的例子咱們能夠看到,咱們經過引用調用了列表,所以對原始列表自己進行了更改。

讓咱們看看另外一個例子:

def updateNumber(n):
    print(id(n))
    n + = 10
b = 5 
print(id(b))#10055680 
updateNumber(b)#10055680 
print(b)#5

在上面的例子中,同一個對象被傳遞給函數,但即便對象是相同的,變量值也不會改變。這被稱爲按價值傳遞 。那麼到底發生了什麼?當函數調用該值時,只傳遞該變量的值,而不傳遞該對象自己。因此引用該對象的變量不會改變,但對象自己正在改變,但僅在函數範圍內。所以,這種變化沒有體現出來。

相關文章
相關標籤/搜索