python的一切變量都是對象枕赵,變量的存儲(chǔ)采用了引用語義的方式猜欺,存儲(chǔ)的只是一個(gè)變量的值所在的內(nèi)存地址,而不是這個(gè)變量的本身拷窜。
基于內(nèi)存地址的分類
Python中的數(shù)據(jù)類型基于內(nèi)存地址分類可以分為:
可變類型: 列表开皿,字典,集合
不可變類型:數(shù)字装黑,字符串副瀑,元組
這里的可變不可變,是指當(dāng)該數(shù)據(jù)類型的對應(yīng)變量的值發(fā)生了改變恋谭,那么它對應(yīng)的內(nèi)存地址是否發(fā)生改變
-
對于不可變類型
變量的每一次初始化,都開辟了一個(gè)新的內(nèi)存空間挽鞠,同時(shí)將新內(nèi)容的地址賦值給變量疚颊。
要注意的是,即使變量對應(yīng)的地址發(fā)生改變信认,但舊地址的內(nèi)容其實(shí)并沒有被修改材义,仍在內(nèi)存中,我們可以通過引入ctypes模塊讀取地址的內(nèi)
-
對于可變類型
當(dāng)對該數(shù)據(jù)類型中的元素進(jìn)行一些增刪改操作的時(shí)候嫁赏,不會(huì)影響到該變量本身的地址其掂,只會(huì)改變其內(nèi)部元素的地址引用。
當(dāng)然潦蝇,如果對其重新初始化(賦值)的時(shí)候款熬,就給該變量重新賦予了一個(gè)新的內(nèi)存地址。
賦值
結(jié)合上面對于可變攘乒、不可變數(shù)據(jù)類型的地址存儲(chǔ)及其地址變化的理解贤牛,我們再來討論P(yáng)ython中對變量的賦值。
Python中的賦值類似于c++中的引用则酝,本質(zhì)是對變量對象的引用殉簸,獲得對方所指向的內(nèi)存地址
-
對于不可變類型
我們對變量的賦值操作,本質(zhì)上只是把等號右邊的值所在的內(nèi)存地址給了左邊的變量
從上圖我們可以看出,a般卑、b均通過賦值得到了“hello world”的內(nèi)存地址之后武鲁,即使對a重新賦值,也只是a得到了新建的值的地址蝠检,對已賦值的b沒有影響
-
對于可變類型
從上圖我們可以看到a洞坑、b均通過賦值得到了一個(gè)列表,雖然表面上我們分別對a蝇率、b列表的內(nèi)容進(jìn)行了修改迟杂,但實(shí)際上修改的卻是內(nèi)存中該列表所指向的內(nèi)部元素,因此本慕,他們的修改會(huì)互相影響(他們本就共用的同一個(gè)列表)
淺拷貝
淺拷貝可用copy模塊中的copy函數(shù)排拷,進(jìn)行淺拷貝時(shí),只會(huì)拷貝該變量元素的地址(可以理解為只拷貝了第一層)锅尘。
我們可以看到监氢,淺拷貝只是新建了一塊內(nèi)存,用于將列表a中的各元素地址拷貝了出來藤违,b得到的是一個(gè)新的內(nèi)存地址浪腐,只不過b所指向的內(nèi)存中各元素地址和a中的相同。
因此顿乒,如果元素是不可變類型议街,則修改只會(huì)改變各自的地址,互相之間沒有影響璧榄,但如果某個(gè)元素是可變類型特漩,則對其內(nèi)容的修改并不會(huì)改變這個(gè)元素本身的地址,就會(huì)互相影響到骨杂。
深拷貝
淺拷貝可用copy模塊中的deepcopy函數(shù)涂身,深拷貝會(huì)完全復(fù)制原變量相關(guān)的所有數(shù)據(jù),在內(nèi)存中生成一套完全一樣的內(nèi)容搓蚪,在這個(gè)過程中我們對這兩個(gè)變量中的一個(gè)進(jìn)行任意修改都不會(huì)影響其他變量蛤售。