尚未建立名稱
能量:0
我的帳號中心
問 學Bot 任何問題!
首頁&搜尋
最愛&收藏
所有課程
分享資源
帳號設定
關於學呀
線上募款
Python中的列表複製
編輯章節
EDU-MD
Google 教室
加至書籤
# Python中的列表複製 在學習完列表(list)的基本使用後,這裡有一個相當重要的重點要獨立出來討論。這個章節中,我們將會關注於**列表的複製**上:這個重點看似簡單,但是在實際使用時,我們經常會忘了它。 ## 「=」的列表宣告 假設現在我們有一個列表 a,帶有許多的數字(已知條件)。今天我們被要求要做出一個列表 b,帶有與列表 a 相同的值,那我們會直覺地這樣寫: ``` >>> a = [1, 3, 5, 7, 9] >>> b = a ``` 這麼一來,我們就可以印出列表 a 和 b,看看兩個列表的值是否相等: ``` >>> print(a) [1, 3, 5, 7, 9] >>> print(b) [1, 3, 5, 7, 9] ``` 的確,兩個列表所帶有的值是相同的,這符合我們的預期。現在,讓我們把列表 b 稍稍地做修正,將 `b[2]` 的位置變成數字 100,並且印出 b: ``` >>> b[2] = 100 >>> print(b) [1, 3, 100, 7, 9] ``` 好的,目前為止事情都符合我們的預期,但是,如果現在將列表 a 印出來呢?我們將會看到什麼?讓我們試試看: ``` >>> print(a) [1, 3, 100, 7, 9] ``` 咦?為什麼 `a[2]` 也跟著變成 100 了?或許你會覺得,為什麼這樣很奇怪?讓我們看看這件事情背後的意義:我們將變數 b 的值宣告為變數 a 的值,然而在我們改變變數 b 後,變數 a 卻跟著改變了! 我們可以比較一下其它不是列表的資料型態,看看它們運作起來與列表有什麼樣的不同: ``` >>> c = 3 >>> d = c >>> d *= 5 >>> print(c) 3 >>> print(d) 15 ``` 當變數是數字時,我們改變變數 d 的值,並沒有改變變數 c 的值。同樣的狀況也會在字串、布林值等資料型態上發生。那麼,我們要如何解釋在列表上發生的神奇現象呢? ## id() 與記憶體的儲存 原來,列表這種資料型態,在電腦記憶體中的運作模式與其它變數有些許的不同。當我們對數字的變數做下列的動作: ``` >>> a = 2 >>> b = a ``` 在第一行程式中,電腦在記憶體中建立了一個數字 2,並且將這個數字賦予給變數 a。在第二行程式中,電腦將剛才建立的那個數字 2 也賦予給變數 b。所以目前為止,a 和 b 兩個變數所代表的值,在記憶體中是相同的數字 2。 ``` >>> b += 3 >>> print(b) 5 >>> print(a) 2 ``` 然而,當我們像上面這樣改變變數 b 的值時,電腦就會在記憶體中建立一個全新的數字,並將其賦予給變數 b。舉例來說,剛才變數 b 和變數 a 都代表著記憶體中相同的一個數字 2,但是當我們執行 `b += 3` 時,電腦就會把變數 b 指向一個記憶體中全新的數字—數字 5。 上述這種狀況,在列表的運作中是不會發生的。我們用相同的動作對兩個全新的 a 和 b 變數進行操作,看看會發生什麼事: ``` >>> a = [1, 3, 5] >>> b = a ``` 在第一行程式中,電腦在記憶體中建立了一個列表,並且建立了 1、3、5 三個數字儲存在列表中,最後將這個列表賦予給變數 a。接著到了第二行,電腦看到了 `b = a` 後,便將剛才的那個列表也賦予給了變數 b。接下來,讓我們試著改變列表 b 中的項目: ``` >>> b[1] = 7 >>> print(b) [1, 7, 5] >>> print(a) [1, 7, 5] ``` 在第一行中,電腦將列表 b 中的 1 號位置(第 2 個位置)改變為 7。此時,不同於數字的是,電腦在列表 b 被改變時,並沒有去改變它在記憶體上的位置。因此,變數 b 跟一開始一樣,與變數 a 指向同一個記憶體的位置。於是我們發現,變數 a 的值也跟著改變了。 要確認電腦有沒有改變的值在記憶體中儲存的位置,在 Python 中是相當簡單的。我們可以使用 Python 的一個內建函數 `id()` 來知道某比資料在記憶體中的確切位置。讓我們看看剛才數字的例子: ``` >>> a = 3 >>> id(a) 140720375994080 >>> b = a >>> id(a) 140720375994080 ``` 在我的電腦上執行時,變數 a 所帶有的數字 3 是儲存在記憶體中編號 140720375994080 的位置的。這裡可以看到,在我們把變數 b 的值設為 a 後,b 變數也一起指向了記憶體中的編號 140720375994080 位置。然後,讓我們改變變數 b: ``` >>> b += 5 >>> id(b) 140720375994240 >>> id(a) 140720375994080 ``` 我們可以看到變數 b 所指向的記憶體位置改變了,而變數 a 還是保持一樣的,因此我們可以知道這時候 a 與 b 是兩個互相獨立、互不關聯的變數。同樣的 `id()` 函數也可以被運用在列表變數上。讓我們跟剛剛一樣宣告兩個列表: ``` >>> a = [1, 3, 5] >>> id(a) 1296034383552 >>> b = a >>> id(b) 1296034383552 ``` 可以看到,變數 a 和變數所代表的列表是同一個列表,而這件事情會一直為真,直到我們將變數 a 或 b 重新定義一個值。 ``` >>> b[1] = 7 >>> id(b) 1296034383552 >>> id(a) 1296034383552 >>> print(a) [1, 7, 5] >>> print(b) [1, 7, 5] ``` 這麼一來我們便知道,當我們要建立一個變數,其值與一個已經存在的列表相同時,不能直接使用等號 `=` 來做變數宣告。不果,如果不能直接使用等號 `=`,那我們該用什麼呢? ## copy() 函數 幸好,在 Python 這個體貼的程式語言中,早就有建立專門執行這項動作的方法。這個方法,屬於列表這個資料型態,叫做 `copy()` 。在使用時,我們可以像下面這樣: ``` >>> a = [1, 3, 5] >>> b = a.copy() ``` 就這樣短短的一兩行程式,我們就成功地將列表 a 複製了一次,代表著電腦在記憶體中已經有了兩個 `[1, 3, 5]` 的列表,而不是像剛才那樣只有一個。因此,如果我們改變列表 b 的值: ``` >>> b[1] = 7 >>> print(b) [1, 7, 5] >>> print(a) [1, 3, 5] ``` 這麼一來,我們就可以成功地複製一個列表,並且不需要擔心列表會不會受到另一個列表的影響。然而,有時這個列表的內容物不一定只是數字—或許列表中還有其它的列表?面對這種**多維列表**,我們複製的方式又不太一樣了。這點,讓我們在之後的章節討論。
複製內容