詳細分析Python可變物件和不可變物件
在 Python 中一切都可以看作為物件。每個物件都有各自的 id,type 和 value。
- id: 當一個物件被建立後,它的 id 就不會在改變,這裡的 id 其實就是物件在記憶體中的地址,可以使用 id() 去檢視物件在記憶體中地址。
- type: 和 id 一樣當物件唄建立之後,它的 type 也不能再被改變,type 決定了該物件所能夠支援的操作
- value: 物件的值
一個物件可變與否就在於 value 值是否支援改變。
不可變物件
常見的不可變物件(immutable objects):
- Number: int,float,complex
- string
- tuple
- frozenset:set 的另外一種型別
讓我們通過例子感受一下
例子
>>> x=1 >>> y=x >>> id(x)==id(y) True >>> id(1)==id(y) True
這裡建立了兩個 int 物件,並且讓 x,y 指向同一個物件,然後我們試著修改一下 x,讓 x+1
>>>x=x+1
這個時候 x 的 id 值和 y 的 id 以及 1 的 id 還一樣嗎?
>>> x=x+1 >>> id(x)==id(y) False >>> id(x)==id(1) False >>> id(1)==id(y) True
從結果不難看出來,x 所指向的物件已經改變了,但是 1 並沒有改變。這就是不可變物件,對於不可變物件來說,一旦建立之後就不允許被改變。
注意: 不可變並不嚴格等同絕對的不可變
>>> a=([1],2,3) >>> id(a) 4338862696 >>> id(a[0]) 4338949128 >>> a[0][0]=0 >>> id(a) 4338862696 >>> id(a[0]) 4338949128
從上面的例子不難看出,我們改變了 a[0] 的值,但是並沒有影響它的 id 值。一個不可變容器物件如果包含對可變物件的引用,當後者的值改變時,前者的值也會改變;但是該容器仍屬於不可變物件,因為它的 id 值不會改變的。
可變物件
常見的可變物件(mutable objects):
- list
- dict
- set
同樣的通過例子感受一下
例子
>>> c = [1,3] >>> b = c >>> id(b)==id(c) True
建立兩個 list 物件,並且讓 c,d 指向同一個物件,然後我們試著修改一下 c
c[0]=4
這個時候在看一下兩個物件的 id 值是否一致
>>> id(c)==id(b) True
修改之後,c,d 仍然指向同一個物件,所以不難得出結論,對於一個可變物件來說,修改 value 值並不會對它的 id 造成任何影響
函式引數
對於可變物件和不可變物件,他們兩者在函式當作引數傳遞的時候表現也有所不同
例子
eg0
def update_list(nums_list): print(f'2 id:{id(nums_list)}') nums_list += [10] print(f'3 id:{id(nums_list)}') number_list = [5,6] print(f'1:{number_list},id:{id(number_list)}') update_list(number_list) print(f'4:{number_list},id:{id(number_list)}')
看一下結果
1:[5,6],id:4457707912
2 id:4457707912
3 id:4457707912
4:[5,6,10],id:4457707912
在看另外一個例子
eg1
def add_num(number): print(f'2:{id(number)}') number += 1 print(f'3:{id(number)}') num = 1 print(f'1:{num},id:{id(num)}') add_num(num) print(f'4:{num},id:{id(num)}')
看一下結果
1:1,id:4343768416
2 id:4343768416
3 id:4343768448
4:1,id:4343768416
有其他有些文章中,上面 eg0 被稱為引用傳遞,eg1 被稱為值傳遞。然而在官方文件中,並沒有找到有關的這兩個名詞的任何內容,或者這種方式並不是上述的兩者任意一種。
這裡的重點是:對於可變物件,在函式中的值的改變,會導致物件改變;對於不可變物件,在函式中值的改變,對其不會造成任何影響
以上就是詳細分析Python可變物件和不可變物件的詳細內容,更多關於Python可變物件和不可變物件的資料請關注我們其它相關文章!