Python可變物件和不可變物件

2022-01-30 08:03:51 字數 2505 閱讀 1300

python中一切皆物件,每個物件都有其唯一的id,對應的型別和值,其中id指的是物件在記憶體中的位置。根據物件的值是否可修改分為可變物件和不可變物件。其中,

不可物件包括:數字,字串,tuple,frozenset(不可變集合)

可變物件包括:list,dict,set

python中的變數可以指向任意物件,可以將變數都看成是指標,儲存了所指向物件的記憶體位址(物件的引用)。

對於不可變物件,如果要更新變數引用的不可變物件的值,會建立新的物件,改變物件的引用,舉個例子:

in [41]: x = 1

in [42]: y = x

in [43]: print(id(x))

140719461487648

in [44]: x = 2

in [45]: print(id(y))

140719461487648

in [46]: print(id(x))

140719461487680

in [47]: print(id(2))

140719461487680

上述是int型別的乙個例項,可以看到:

想要變數的值,會在記憶體中建立乙個新的物件,變數指向新的物件。

對於值為1或者2,不管幾個引用指向它,記憶體中都只占用了乙個位址,在python內部會通過引用計數來記錄指向該位址的引用個數,當引用個數為0時會進行垃圾**。

所以,不可變物件的優點是對於相同的物件,無論多少個引用,在記憶體中只占用乙個位址,缺點是更新需要建立新的物件,因此效率不高。

對於可變物件,舉個例子:

in [57]: a = [1, 2]

in [58]: b = a

in [59]: print(id(a), id(b))

1961088949320 1961088949320

in [61]: print(a, b)

[1, 2, 3] [1, 2, 3]

in [62]: print(id(a), id(b))

1961088949320 1961088949320

in [63]: a = [1, 2, 3]

in [64]: print(id(a))

1961088989704

可以看到:

值的變化是在原有物件的基礎上進行更新的,變數引用的位址沒有變化。

對於乙個變數的兩次賦值操作,值相同,但是引用的位址是不同的,也就是同樣值的物件,在記憶體中是儲存了多份的,位址是不同的。

in [96]: a = [1, 2, 3]

in [97]: b = a

in [98]: a = [1]

in [99]: b

out[99]: [1, 2, 3]

因為可變物件和不可變物件的特性,因此在引數傳遞上需要注意,詳情可參考 我的回答

首先,舉個例子:

in [69]: data = [, , ]

in [70]: print(data)

[, , ]

in [71]: def add(data_list):

...: for item in data_list:

...: if item.get('deleted'):

...: data_list.remove(item)

...: return data_list

...:

in [72]: add_result = add(data)

in [73]: print(add_result)

[, ]

in [74]: print(data)

[, ]

你會發現呼叫了add方法之後,data已經變了,在之後的**中你已經無法再使用原來的data了,具體的原因在引數傳遞那個問題中我有說明。

但是,當你希望在add方法中並不會修改data的值,要怎麼做呢?

這時候,你需要了解下深拷貝和淺拷貝:

深拷貝和淺拷貝的概念:

淺拷貝(shallow copy):構造乙個新的物件並將原物件中的引用插入到新物件中,只拷貝了物件的位址,而不對對應位址所指向的具體內容進行拷貝,也就是依然使用原物件的引用。實現方式包括:工廠函式(list, set等)、切片,copy模組的copy方法。

深拷貝(deep copy):複製了物件的和引用,深拷貝得到的物件和原物件是相互獨立的。實現方式:copy模組的deepcopy方法。

所以,上述**可按需更新為:

def add(data_list):

ret_data_list = deepcopy(data_list)

for item in ret_data_list:

if item.get('deleted'):

ret_data_list.remove(item)

return ret_data_list

以上。

python 可變物件和不可變物件

變數沒有型別,那麼就意味著它可以隨意指向任何物件。python中的變數相當於乙個指標。當將乙個變數a賦值給另乙個變數b時,無論變數a指向的是可變物件還是不可變物件,變數b指向變數a指向的物件。例 alist 1 2,3 anolist alist id alist id anolist true b...

Python 可變物件和不可變物件

python在heap中分配的物件分成兩類 可變物件和不可變物件。所謂可變物件是指,物件的內容是可變的,例如list。而不可變的物件則相反,表示其內容不可變。一 不可變物件 由於python中的變數存放的是物件引用,所以對於不可變物件而言,儘管物件本身不可變,但變數的物件引用是可變的。從上面得知,不...

可變物件和不可變物件

要理解可變物件和不可變物件,先要理解final關鍵字。參考此部落格 沒有經過原博主的同意便引用了一些,侵刪!final關鍵字可以用來修飾類 方法和變數 成員或區域性 final修飾類時表明這個類不能被繼承。final類中的方法會被隱式的定義為fianl,變數自行定義需要不要被final修飾。fina...