導航:首頁 > 編程語言 > 不可變對象python

不可變對象python

發布時間:2023-03-31 02:33:42

『壹』 誰能給簡單通俗點解釋下python里可變對象、不變對象、變數三者的關系

①python中,萬物皆對象。
②python中,沒有絕對常量,有的是對常量的引用。
③python中,可變對象,表示的是對象內容可以改變,比如list ,dist
④python中,不可變對象,表示的是對象內容不可以改變,如字元串,tuple等
變數和對象,這兩個很難解釋,我個人理解是,比如在python中 i = 1,i是一個變數,也同時是一個對象,在python中, 變數和對象的區別不大,請看第①條。

如同 str = "Hello", str是變數(也是對象),而"Hello"就是常量了,str變數指向"Hello"。

所說的字元串重新賦值,只不過是創建了新的字元串,讓變數指向這個新的地址罷了。

『貳』 Python對象的拷貝

Python賦值操作或函數參數傳遞,傳遞的永遠是對象引用(即內存地址),而不是對象內容。在Python中一切皆對象,對象又分為可變(mutable)和不可變(immutable)兩種類型。對象拷貝是指在內存中創建新的對象,產生新的內存地址。當頂層對象和它的子元素對象全都是immutable不可變對象時,不存在被拷貝,因為沒有產生新對象。淺拷貝(Shallow Copy),拷貝頂層對象,但不會拷貝內部的子元素對象。深拷貝(Deep Copy),遞歸拷貝頂層對象,以及它內部的子元素對象。

Python中一切皆對象,對象就像一個塑料盒子, 裡面裝的是數據。對象有不同類型,例如布爾型和整型,類型決定了可以對它進行的操作。現實生活中的"陶器"會暗含一些信息(例如它可能很重且易碎,注意不要掉到地上)。

對象的類型還決定了它裝著的數據是允許被修改的變數(可變的mutable)還是不可被修改的常量(不可變的immutable)。你可以把不可變對象想像成一個透明但封閉的盒子:你可以看到裡面裝的數據,但是無法改變它。類似地,可變對象就像一個開著口的盒子,你不僅可以看到裡面的數據,還可以拿出來修改它,但你無法改變這個盒子本身,即你無法改變對象的類型。

對象拷貝是指在內存中創建新的對象,產生新的內存地址。

淺拷貝(Shallow Copy),拷貝頂層對象,但不會拷貝內部的子元素對象。
2.1.1. 頂層是mutable,子元素全是immutable
當頂層對象是mutable可變對象,但是它的子元素對象全都是immutable不可變對象時,如[1, 'world', 2]

① 創建列表對象並賦值給變數a

② 導入模塊,使用.()函數淺拷貝a,並賦值給變數b

③ 修改變數a的子元素a[0] = 3,由於整數是不可變對象,所以並不是修改1變為3,而是更改a[0]指向對象3

當頂層對象是 mutable可變對象 ,但子元素也存在 mutable可變對象 時,如 [1, 2, ['hello','world']]

① 淺拷貝 .() 只拷貝了頂層對象,沒有拷貝子元素對象['hello','world'],即a[2]和b[2]指向同一個列表對象

② 修改a[2][1] = 'china',則b[2][1] = 'china'

當頂層對象是immutable不可變對象,同時它的子元素對象也全都是immutable不可變對象時,如(1, 2, 3)

變數a與變數b指向的是同一個元組對象,沒有拷貝

當頂層對象是immutable不可變對象時,但子元素存在mutable可變對象時,如(1, 2, ['hello','world'])

變數a與變數b指向的是相同的元組對象,並且a[2]與b[2]指向同一個列表,所以修改a[2][1]會影響b[2][1]

深拷貝(Deep Copy),遞歸拷貝頂層對象,以及它內部的子元素對象

當頂層對象是mutable可變對象,但是它的子元素對象全都是immutable不可變對象時,如[1, 'world', 2]

變數a與變數b指向不同的列表對象,修改a[0]只是將列表a的第一個元素重新指向新對象,不會影響b[0]

當頂層對象是mutable可變對象,但子元素也存在mutable可變對象時,如[1, 2, ['hello','world']]

深拷貝既拷貝了頂層對象,又遞歸拷貝了子元素對象,所以a[2]與b[2]指向了兩個不同的列表對象(但是列表對象的子元素初始指定的字元串對象一樣),修改a[2][1] = 'china'後,它重新指向了新的字元串對象(內存地址為140531581905808),不會影響到b[2][1]

當頂層對象是immutable不可變對象,同時它的子元素對象也全都是immutable不可變對象時,如(1, 2, 3)

變數a與變數b指向的是同一個元組對象,不存在拷貝

當頂層對象是immutable不可變對象時,但子元素存在mutable可變對象時,如(1, 2, ['hello','world'])

變數a與變數b指向的是不同的元組對象,同時a[2]與b[2]指向不同的列表對象,所以修改a[2][1]不會影響b[2][1]

使用=是賦值,即將列表對象的引用也賦值給變數b,可以將列表對象想像成一個盒子,變數a相當於這個盒子上的標簽,執行b = a後,相當於再在這個盒子上貼上b標簽,a和b實際上指向的是同一個對象。因此,無論我們是通過a還是通過b來修改列表的內容,其結果都會作用於雙方。

b/c/d都是a的復制,它們都指向了不同的列表對象,但是沒有拷貝子元素,a[2]和b[2]/c[2]/d[2]指向同一個列表, 相當於淺拷貝的效果

使用分片[:]操作,a和b其實是指向同一個元組,而且沒有拷貝子元素,a[2]和b[2]也指向同一個列表,相當於淺拷貝的效果

同列表類似,可以使用字典的()函數或者轉換函數dict()

變數a與變數b/c指向不同的字典,但是沒有拷貝子元素,a['jobs']和b['jobs']/c['jobs']指定同一個列表, 相當於淺拷貝的效果

同列表類似,可以使用集合的()函數或者轉換函數set()

變數a與變數b/c指向不同的集合,而集合的元素必須是hashable,所以修改集合a不會影響到b/c

『叄』 Python不可變對象元組(tuple)詳解

元組和列表飢肢配很相似,不過元組是不能在原處改變的對象,這點性質和字元串一致,雖然元組不支持任何方法調用,但是元組具有列表的大多數屬性,以下是元組的一些特性。

示例結果:

示例結果:

示例結果:

示例結果:

示例結果:

當我們在學習元組時,總是會納悶爛指已經有了列表為什麼還需要學習使用元組看似雞肋的內置對象呢? 我們可以通過元組的不可變性運用在一些場景中,因為其不可變性本身本身就提供了某種完整性,比如使用元組來實現函數的多返回值飢鏈,作為參數傳遞給函數調用、或是從函數調用那裡獲得參數時,保護其內容不被外部介面修改。

『肆』 Python 中的可變類型對象和不可變類型是什麼意思

不可變數據類型對象是指,當一個對象創建成功後,該變數就記錄攜肢了一個常量值在內存中的地址.當對該不可變對象進行賦值時,並沒有改變對象所代表的常量值,而是重新記錄了被賦值賣隱慧對象在內存中的地址,
可變數據類型對象可以理解成是一個容器,在這個容器中,可以承載多個相同或不同的數據.並且,容器中的數據可以被替換修改等操中答作.
Python的可變型和不可變類型知道是什麼了吧,如果學習Python不知道去哪裡找學習資料,可以看黑馬程序員,有學習資料、視頻、技術等等!

『伍』 python 里的可變對象與不可變對象具體怎麼理解

Python的數據類型分為可變(mutable)與不可變(immutable)。不可變類型包含字元串(str),整數(int),元組(tuple);可變類型包含列表(list),字典(dict)。
是否為可變類型在於內存單元的值是否可以被改變。如果是內存單元的值不可改變的,在對對象本身操作的時候,必須在內存的另外地方再申請一塊內存單元(因困遲為老的內存單元不可變),老鏈孫的內存單元就丟棄了(如果還有其他ref,則ref數字減1,類似unix下的hard-link);如果是可變的,對對象操作的時候,棚尺鏈不需要再在其他地方申請內存,只需要在此對象後面連續申請(+/-)即可,也就是它的地址會保持不變,但區域會變長或者變短。

『陸』 Python,明明只append了一次,為什麼所有子列表都變了啊.jpg

a 和 b 有何不同?有的同學可能會覺得這兩種方法的結果是一樣的,都是:

然而真實的結果是:

為什麼會產生不同的結缺吵神果呢?明明只append了一次,為什麼 a 中的所有子列表都變了呢?這要從 Python 的數據模型說起。

Python 中每個對象都有各自的編號、類型和值。一個對象被創建後,它的編號就絕不會改變,你可以將其理解為該對象在內碰碰存中的地址。 Python 還提供了 is 運算符和 id() 函數用於比較和查看對象的編號。

is 運算符可以比較兩個對象的編號是否相同; id() 函數能返回一個代表其編號的整型數。

在 Python 中有些對象的值可以改變,有些不可以。值可以改變的對象被稱為可變對象;值不可以改變的對象就被稱為不可變對象。(一個不可變容器對象如果包含對可變對象的引用,當後者的值改變時,前者的值也會改變;但是該容器仍屬於不可變對象,因為它所包含的對象集是不會改變的。因此,不可變並不嚴格等同於值不能改變,實際含義要更微妙。) 一個對象的可變性是由其類型決定的;例如,數字、字元串和元組是不可變的,而字典和列表是可變的。 [1]

在一開始的問題中,列表 a 初始化的時候,內層的子列表 [] 實際上是引用了同一個可變對象。因此對內層的任意一個子列表的 append() 操作,最終會因為引用了同一個對象的原因,體現在每一個子列表上。

而 b 初始化的時候是創建了3個不同 [] 對象。每個子列表引用了不同的對象。

在 Python 的官方文檔中也說明了這種情況, lst * n 這種形式相當於 lst 與自身進行 n 次拼接。 lst 中的項不會被拷貝,而是會進行多次引用。 [2]

我們再深入的看一下剛才括弧里伏虧面很拗口的那句話:

「一個不可變容器對象如果包含對可變對象的引用,當後者的值改變時,前者的值也會改變;但是該容器仍屬於不可變對象,因為它所包含的對象集是不會改變的。因此,不可變並不嚴格等同於值不能改變,實際含義要更微妙。」

簡單做個實驗:

我們可以看到 a 、 b 是可變對象,而 c 是不可變容器對象。我們改變了 a 的值,可以看到 a 的編號沒有發生改變,這個很正常,因為 a 是可變對象。
同時因為 c 中的元素包括 a ,所以 c 的「值」也發生了變化,但是 c 的編號沒有變化,也就是說還是那個不可變對象。也就是說 c 的不變性是基於它的對象集沒有變化。

『柒』 Python中的元組(Tuple)

在Python中,元組(Tuple)與列表(List)類似,也是一個有序的序列,但元組是一個不可變對象,其一旦初始化後便無法進行修改。

一般在創建元組時,分為創建空元組和非空元組,其創建方式如下:

從上面可以看到,我們只需要把元組的所有元素放在 小括弧 () 裡面,每個元素之間通過 逗號 , 間隔起來即可,當然和列表一樣,元組中同樣允許存放不同數據類型的元素。

元組中使用的 () 是常見的數學運算符,如果參考列表的創建,如下:

從上面可以看到,我們創建出來的壓根就不是元組類型。那麼我們想創建一個只包含一個元素的元組時,需要怎麼創建呢?

很簡單,只需要在元素後加上一個 逗號 , ,這樣創建出來就是一個元組。

當我們需要訪問元組中的元素,可以類似列表一樣通過索引取值或切片取值。

如果訪問的索引不存在,那麼會報錯: IndexError: tuple index out of range

在元組中,可以像列表一樣使用切片,語法為: 元組[start:end:step] ,通過切片可以獲取到元組中指定范圍的元素,返回結果是一個新元組。在這里,需要注意切片的規則是左閉右開,也就是說包含頭部 start,但不包含尾部 end ,而 step 則表示切片的步長,需要每間隔 step 個元素取一次。

在上面我們提到了元組是不可變的,這就意味著我們創建一個元組之後,不能再去改變其值了,比如下面這樣就會出現報錯:

假設元組中存在元素是一個可變對象,如果我們不改變元組,但改變了可變對象的值,又會得到怎麼的結果呢?請看下面實例:

從上面可以看到,元組中的第 2 個元素似乎發生了變化,這豈不是和上面說的元組不可變自相矛盾了嗎?

其實,我們說的元組不可變,指的是元組中各元素的指向永遠保持不變。在上面操作中,元組中第 2 個元素指向的一直是 列表nums ,我們改變的其實不是元組的元素,而只是改變了 列表nums 中的元素。

元組是不可變的,因此我們就不能刪除元組中的元素,但是,我們可以通過 del 語句刪除整個元組。

通過關鍵字 in ,可檢查當前元組中是否包含指定元素,返回結果為布爾值 True 或 False。

通過關鍵字 in ,還可以用於遍歷當前元組。

『捌』 Python3 & 淺拷貝與深拷貝

在Python中對象的賦值(=)其實就是對象的引用。即:當創建一個對象,把它賦值給另一個變數時,python並沒有拷貝這個對象,只是拷貝了這個對象的引用而已。

Python中對象的拷貝分為:淺拷貝()和深拷貝(deep)。
淺拷貝:拷貝了最外圍的對象本身,內部的元素都只是拷貝了一個引用而已。也就是,將原對象在內存中引用地址拷貝過來,然後讓新的對象指向這個地址。可以使用「=」或列表自帶的()函數(如list.()),或使用模塊的()函數。

深拷貝:外圍和內部元素磨碰都進行了拷貝對象本身,而不是引用。即把對象復制一遍,並且該對象中引用的其他對象也同時復制,完全得到一個新的一模一樣的對象,對新對象里的值進行修改不會影響原有對象,新對象和原對象完全分離開。深拷貝只能使用模塊中deep()函數,使用前要含高導入:from import deep。

Python中對象分為不可變對象 、可變對象。
不可變對象:一旦創建就不可修改的對象,例如:字元串、元組、數字
可變對象:可以修改的對象,例如:列表、字典。
其中Python中的切片可以應用於:列表、元組、字元串,但不能應用於字典。
而深淺拷貝,可應用於序列(列表、元組、字元串),也可應用於字典。
其中不可變對象,不管是深拷貝還是淺拷貝,地址值在拷貝後的值都是一樣的。

以下以元組(不可變類型)為例

從上述示例可以看出:
不可變對象類型,沒有被拷貝的說法,即便是用深拷貝,查看id的話也是一樣的,如果對其重新賦值,也只是新創建一個對象,替換掉舊的而已。
所以不可變類型,不管是深拷貝還是淺拷貝,地址值和拷貝後的值都是一樣的。

以下以列瞎老談表(可變類型)為例
第一種方法:使用=號淺拷貝

輸出結果:

第二種方法:使用淺拷貝

輸出結果:

第三種方法:使用deep深拷貝

輸出結果:

從上述示例可以看出:
=淺拷貝:值相等,地址相等
淺拷貝:值相等,地址不相等
deep深拷貝:值相等,地址不相等

總結:
1,深淺拷貝都是對源對象的復制,佔用不同的內存空間。
2,不可變類型的對象,對於深淺拷貝毫無影響,最終的地址值和值都是相等的。
3,可變類型的對象,使用=淺拷貝時, 值相等,地址相等,對新對象里的值進行修改同時會影響原有對象;使用淺拷貝時值相等,地址不相等;使用deep深拷貝時值相等,地址不相等。可以看出針對可變類型淺拷貝和deep深拷貝,對新對象里的值進行修改不會影響原有對象。

『玖』 python-進階-對象變動 a += 1與a = a+1區別

Python中 可變(mutable)與不可變(immutable)的數據類型 讓新手很是頭辯伏痛。簡單的說,可變(mutable)意味著"可以被改動",而不可變(immutable)的意思是「常量(constant)」。想把腦筋轉動起來嗎?考慮下這個例子:

剛剛發生了什麼?我們預期的不是那樣!

這不是一個bug。這是對象可變性(mutability)在作怪。 每當你將一個變數賦值為另一個可變類型的變數時,對這個數據的任意改動會同時反映到這兩個變數上去。新變數只不過是老變數的一個別名而已。這個情況只是針對可變數據類型

啊哈!這次又沒有達到預期, 是列表的可變性在作怪 。在Python中當函數被定義時,默認參數只會運算一次,而不是每次被調用時都會重新運算。你應該永遠不要定義可變類型的默認參數,除非你知道你正在做什麼。你應該像這樣做:

現在每當你在調用這個函數不傳入target參數的時候,一個新的列表會被創建。舉個例子:

為什麼會出現這樣?

a+=b

a=a+b

顯然,兩者是有區別的,而這種區別只出現在可變對象上(為什麼攜扒攜是可變對象後面再說),是什麼原因造成了兩者的區別呢?

+= 操作調用 __iadd__ 方法,沒有該方法此行時,再嘗試調用 __add__ 方法

__iadd__ 方法 直接在原對象a1上進行更新,該方法的返回值為None

+ 操作調用 __add__ 方法

__add__ 方法會返回一個新的對象,原對象不修改,因為這里 a1被重新賦值了,a1指向了一個新的對象,所以出現了文章開頭a1不等於a2的情況

為什麼前面我說這種差異只會發生的 可變對象 身上?因為對於不可變對象,根本沒有 __iadd__ 方法,所以 += 和 + 的效果是一樣的,因為調的都是 __add__ 方法

『拾』 Python 的傳參是傳值還是傳址

Python對可變對象(字典或列表)傳址,
對不可變對象(數字、字元或元祖)傳值。

閱讀全文

與不可變對象python相關的資料

熱點內容
電影大全鬼片免費收看 瀏覽:147
kanxv5. com/6/ index.php/ 瀏覽:584
看外國電影的網站 瀏覽:18
染島貢演過的電影 瀏覽:79
經典系列動作電影 瀏覽:730
勞拉是哪個電影里的名字 瀏覽:677
天才黑客林凡 瀏覽:514
中國電影票房排行榜實時票房貓眼 瀏覽:287
收母收姐妹 瀏覽:378
一男兩女後面兩女懷孕的番號 瀏覽:555
不需要會員就能看電視劇的網站 瀏覽:427
朝鮮古裝三及片 瀏覽:113
手機怎麼設置不解壓 瀏覽:110
崇石是誰演的 瀏覽:827
免費影視觀看網站入口 瀏覽:877
為什麼伺服器會出現很多藍屏 瀏覽:34
三國種馬收了何皇後 瀏覽:344
思甜APP怎麼樣 瀏覽:525
床戲美國 瀏覽:763
醉猴拳電影在線觀看 瀏覽:832