舉例子來說明Python引用和對象,python引用

來源:互聯網
上載者:User

舉例子來說明Python引用和對象,python引用

今天看到這麼一句奇怪的話: python中變數名和對象是分離的;最開始的時候是看到這句話的時候沒有反應過來。決定具體搞清楚一下python中變數與對象之間的細節。(其實我感覺應該說 引用和對象分離 更為貼切)

  從最開始的變數開始思考:

   在python中,如果要使用一個變數,不需要提前進行聲明,只需要在用的時候,給這個變數賦值即可 (這個和C語言等靜態類型語言不同,和python為動態類型有關)。

   舉第一個例子:

    a = 1

   這是一個簡單的指派陳述式,整數 1 為一個對象,a 是一個引用,利用指派陳述式,引用a指向了對象1;這邊形象比喻一下:這個過程就相當於“放風箏”,變數a就是你手裡面的“線”,python就跟那根“線”一樣,通過引用來接觸和拴住天空中的風箏——對象。

   你可以通過python的內建函數 id() 來查看對象的身份(identity),這個所謂的身份其實就是 對象 的記憶體位址:

    註:

     python一切皆對象的理念,所以函數也是一個對象,因此可以使用 id() 函數的__doc__方法來查看這個函數的具體描述。


先舉個例子:
>>> a = 1>>> id(a)24834392>>> a = 'banana'>>> id(a)139990659655312

第一個語句中, 2是儲存在記憶體中的一個整數對象,通過賦值 引用a 指向了 對象 1;

第二個語句中,記憶體中建立了一個字串對象‘banana’,通過賦值 將 引用a 指向了 ‘banana’,同時,對象1不在有引用指向它,它會被python的記憶體處理機制給當我記憶體回收,釋放記憶體。


再舉一個例子:
>>> a = 1>>> id(a)24834392>>> a = 'banana'>>> id(a)139990659655312

第一個語句中, 2是儲存在記憶體中的一個整數對象,通過賦值 引用a 指向了 對象 1;

第二個語句中,記憶體中建立了一個字串對象‘banana’,通過賦值 將 引用a 指向了 ‘banana’,同時,對象1不在有引用指向它,它會被python的記憶體處理機制給當我記憶體回收,釋放記憶體。

 

再來一個例子:
 

通過函數查看 變數a 和 變數b的引用情況: 

123456 >>> a = 3>>> b = 3>>> id(a)10289448>>> id(b)10289448

  在這裡可以看到  這倆個引用 指向了同一個 對象,這是為什麼呢? 這個跟python的記憶體機制有關係,因為對於語言來說,頻繁的進行對象的銷毀和建立,特別浪費效能。所以在Python中,整數和短小的字元,Python都會緩衝這些對象,以便重複使用。


然後再看看這個例子:
 

 1.  a = 4

    2.  b = a(這裡就是讓引用b指向引用a指向的那個對象)

    3.  a = a + 2

   通過函數查看引用情況:

    當執行到第2步的時候,查看一下 a 和 b 的引用:      

123456 >>> a = 4>>> b = a>>> id(a)36151568>>> id(b)36151568

    可以看到 a 和 b 都指向了 整數對象 4

    接下來指向第3步:

12345 >>> a = a+2>>> id(a)36151520>>> id(b)36151568

    可以看到 a 的引用改變了,但是 b 的引用未發生改變;a,b指向不同的對象; 第3句對 a 進行了重新賦值,讓它指向了新的 對象6;即使是多個引用指向同一個對象,如果一個引用值發生變化,那麼實際上是讓這個引用指向一個新的引用,並不影響其他的引用的指向。從效果上看,就是各個引用各自獨立,互不影響。
 

還有一個必須要看的例子:
l1 = []a = 0for i in range(1,5):    a = i    l1.append(a) # 添加的是a指向的對象print(l1) # [1, 2, 3, 4]l2 = []b = [1,2,3]for i in range(1,5):    b[1] = i    l2.append(b) # 添加的是b指向的對象,它包括列表元素的引用,列表本身沒有改變,只是清單項目[1]指向的對象變了print(l2) # [[1, 4, 3], [1, 4, 3], [1, 4, 3], [1, 4, 3]]# 不是預料的 [[1, 1, 3], [1, 2, 3], [1, 3, 3], [1, 4, 3]]

所以,每次列表實際上都是添加同一個對象。

l2 = []b = [1,2,3]for i in range(1,5):    b[1] = i    l2.append(copy.copy(b))    # l2.append(copy.deepcopy(b)) 和copy.copy()結果一樣print(l2) # [[1, 1, 3], [1, 2, 3], [1, 3, 3], [1, 4, 3]]

copy.copy() 淺拷貝。只拷貝父物件,不會拷貝對象的內部的子物件。

那麼,copy.copy()和copy.deepcopy()有什麼區別呢?

l2 = []b = [1,[4,5],3]for i in range(1,5):    b[1][0] = i    l2.append(copy.copy(b)) # [[1, [4, 5], 3], [1, [4, 5], 3], [1, [4, 5], 3], [1, [4, 5], 3]]    # l2.append(copy.deepcopy(b)) # [[1, [1, 5], 3], [1, [2, 5], 3], [1, [3, 5], 3], [1, [4, 5], 3]]print(l2)

copy.deepcopy() 深拷貝 拷貝對象及其子物件。

最後一個例子:

(這個栗子會涉及到 python中的 可變資料類型 和 不可變資料類型):

   開始這個栗子之前,請記得注意到 第四個栗子的不同之處。

     1.   L1 = [1, 2, 3]

     2.   L2 = L1

     3.   L1[0] = 10

   通過函數查看引用情況:

   當執行第1步 和 第二步 的時候,查看一下 L1 和 L2 的引用情況:

123456 >>> L1 = [1,2,3]>>> L2 = L1>>> id(L1)139643051219496>>> id(L2)139643051219496

此時 L1 和 L2 的引用相同,都是指向 [1,2,3]這個列表對象。

接下來,繼續執行第3步:

1234567 >>> L1[0= 10>>> id(L1)139643051219496>>> id(L2)139643051219496>>> L2[1023]

同樣的跟第四個栗子那樣,修改了其中一個對象的值,但是可以發現 結果 並不與 第四個栗子那樣, 在本次實驗中,L1 和 L2 的引用沒有發生任何變化,但是 列表對象[1,2,3] 的值 變成了 [10,2,3](列表對象改變了)


在該情況下,我們不再對L1這一引用賦值,而是對L1所指向的表的元素賦值。結果是,L2也同時發生變化。


原因何在呢?因為L1,L2的指向沒有發生變化,依然指向那個表。表實際上是包含了多個引用的對象(每個引用是一個元素,比如L1[0],L1[1]..., 每個引用指向一個對象,比如1,2,3), 。而L1[0] = 10這一賦值操作,並不是改變L1的指向,而是對L1[0], 也就是表對象的一部份(一個元素),進行操作,所以所有指向該對象的引用都受到影響。

(與之形成對比的是,我們之前的賦值操作都沒有對對象自身發生作用,只是改變引用指向。)


列表可以通過引用其元素,改變對象自身(in-place change)。這種物件類型,稱為可變資料對象(mutable object),詞典也是這樣的資料類型。


而像之前的數字和字串,不能改變對象本身,只能改變引用的指向,稱為不可變資料對象(immutable object)。


我們之前學的元組(tuple),儘管可以調用引用元素,但不可以賦值,因此不能改變對象自身,所以也算是immutable object.

感謝閱讀上海尚學堂python文章,擷取更多文章和支援人員,請點擊 上海Python培訓
 推薦一下相關文章:《Python基礎學習之字元編碼、互動輸入和字串拼接》;《談談Python中的*args 和 **kwargs》;《Python的函數參數傳遞》等

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.