list[] 和 list[:] 的區別


list[] 和 list[:] 的理解

  list“賦值”時會用到list2 = list1 或者 list2[:] = list1,前者兩個名字指向同一個對象,后者兩個名字指向不同對象。理解如下:

 

  首先,python中沒有賦值的說法,只有名稱到對象的引用;

  list2 = list1是把list1所指的對象綁定到名字list2上,沒有產生新list,只是新增了一個引用;

  正因為兩個名稱指向的同一個對象,所以修改list1,那么list2也會改變;

  通俗理解:以前有一套三室一廳的房子,戶主叫list1。后來list1和list2結婚,房產證上戶主的名字加了一個,但房子還是只有一套。list1如果把客廳刷成了藍色,那list2回家的時候會發現客廳是藍色的了。

 

  而list2 = list1[:]則是把list1通過切片運算取得的新list對象綁定到list2上,產生了新list,名稱和引用也不同,所以,修改其中一個,另一個不會變。

  注意,這里的切片是淺拷貝,參考下面的筆記。

  通俗理解:從前有一套三室一廳的房子,戶主叫list1。后來有個叫list2的,覺得list1的房子不錯,於是買了一套相同戶型的,也裝修得一模一樣。后來list1把自己的客廳刷成了藍色,list2回家發現自己家的客廳還是白色,並沒有變成藍色。

 

淺拷貝(shallow copy)

  淺拷貝會創建新對象,其內容是原對象的引用。

  淺拷貝有三種形式:切片操作,工廠函數,copy模塊中的copy函數。

  比如對:a = [1,2,3,"hello",["python","C++"]]

    1、切片操作:b = a[:] 或者 b = [each for each in a]

    2、工廠函數:b = list(a)

    3、copy函數:b = copy.copy(a)

  淺拷貝產生的b不再是a了,使用is可以發現他們不是同一個對象,使用id查看,發現它們也不指向同一片內存。但是當我們使用 id(x) for x in a 和 id(x) for x in b 時,可以看到二者包含的元素的地址是相同的。

  在這種情況下,a和b是不同的對象,修改b理論上不會影響a。

  比如b.append([4,5]):

  b = a[:]

  b.append("ADD")

  輸出:a [1, 2, 3, 'hello', ['python', 'C++']] b [1, 2, 3, 'hello', ['python', 'C++'], 'ADD']

  注:淺拷貝之所以稱為淺拷貝,是它僅僅只拷貝了一層,在a中有一個嵌套的list,如果我們修改了它,情況就不一樣了。

   a[4].append("C")。查看b,可發現b也發生了變化。這是因為,我們修改了嵌套的list。修改外層元素,會修改它的引用,讓它們指向別的位置,修改嵌套列表中的元素,列表的地址並為發生變化,指向的都是同一個位置。

 

深拷貝(deep copy)

  深拷貝只有一種形式,copy模塊中的deepcopy函數。

  和淺拷貝對應,深拷貝拷貝了對象的所有元素,包括多層嵌套的元素。因而,它的時間和空間開銷要高。

  同樣對上述list類型的a,若使用b = copy.deepcopy(a),再修改b將不會影響到a了。即使嵌套的列表具有更深的層次,也不會產生任何影響,因為深拷貝出來的對象根本就是一個全新的對象,不再與原來的對象有任何關聯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM