0%

Python 的 list

為什麼要用到 list ?

舉個例子:

1
names = 'Rogers Stark Thor Loki Natasha'

雖然 names 可以存取人名,但是如果要增加或者存取其中一個人的名字就GG。

所以我們使用 list 來存取這些人名,list在python是以[]來表示的。

而且list內容是可以更改的,像是排序、加入、刪除等等。

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']

取得 list 的值

這時我想要得到Jenny,該怎麼取呢?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
print(names[4])
4
5
---------執行結果-------
6
7
Jenny

等等Jenny不是在第五個嗎?怎麼會是names[4]?
這是因為電腦存數據時,不是從1開始算的,是從0開始算起的,所以Jenny是在第四個。
我們可以使用[index]來取出list的值囉,跟C語言的array類似。

那…能不能一次把 ‘Tim’和’Amy’取出來?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
print(names[2:3])
3
4
---------執行結果---------
5
6
['Tim']

奇怪?[2:3] 不是2~3的意思嗎?怎麼只有Tim一個人?

哦~~原來我用法錯誤!!
正確是這樣

[Start:End-1]
end是要減1的
使用[Start:End-1] return 是一個 list 喔!

如果我不知道list有幾個,但我想取出最後一個怎麼辦?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
print(names[-1])
3
4
---------執行結果---------
5
Jenny

所以正的(包含0)就是從左到右取值,負的就是從右到左取值,所以倒數第二個就是names[-2]

那這樣取全部是不是這樣?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
print(names[0:-1])
3
4
5
---------執行結果---------
6
['Mike', 'John', 'Tim', 'Amy']

拉雞!又不對,阿!我忘了是 使用[Start:End-1]

所以應該是names[0:0],但這個很鳥欸 = =

有個更牛逼的方法,就是如果你要頭跟尾就空白。

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
print(names[:2]) # 第0個到第1個
4
print(names[1:]) # 第1個到最後1個
5
print(names[:])  # 全部
6
7
---------執行結果---------
8
9
['Mike', 'John']
10
['John', 'Tim', 'Amy', 'Jenny']
11
['Mike', 'John', 'Tim', 'Amy', 'Jenny']

棒!果然如預期!

加入元素

喔喔 突然要加一個人,要怎麼加呢?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
names.append("Curry")
3
4
print("After append() ",names)
5
6
---------執行結果---------
7
['Mike', 'John', 'Tim', 'Amy', 'Jenny','Curry']

append()是list內建function功能是加進list的尾端

但是我想加到list的任何位置怎麼辦?

1
2
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
3
names.insert(1,"insert1_Jack")
4
names.insert(3,'insert3_Tom')
5
6
---------執行結果---------
7
['Mike', 'insert1_Jack', 'John', 'insert3_Tom', 'Tim', 'Amy', 'Jenny']

原本在[1]的’John’被往後移一格了,’Tim’也是,代表insert()不會取代原來的元素。

串接list

要把一個list接在令一個list要怎麼用呢?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
others = ['Tom','Curry']
3
4
names.append(others)
5
print(names)
6
7
---------執行結果---------
8
['Mike', 'John', 'Tim', 'Amy', 'Jenny', ['Tom', 'Curry']]

好像不是這樣弄呢…others被當成一個項目加尾端了

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
others = ['Tom','Curry']
3
names.extend(others)
4
print(names)
5
6
---------執行結果---------
7
['Mike', 'John', 'Tim', 'Amy', 'Jenny', 'Tom', 'Curry']

喔喔使用extend()救解決了這個問題

取代

那如果names第二個要改成Faker要怎麼取代呢?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
names[1] = 'Faker'
3
print(names)
4
5
---------執行結果---------
6
['Mike', 'Faker', 'Tim', 'Amy', 'Jenny']

有了John被改成我們要的Faker了

刪除

那怎麼刪除人名呢?
有三種方法,我們來刪除Amy。

1
2
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
3
4
# 三種方法delete
5
6
# 1. names.remove("Amy")
7
# 2. del names[3]
8
# 3. names.pop(3)
9
10
names.pop(3)   #使用pop()
11
print(names)
12
13
---------執行結果---------
14
['Mike', 'John', 'Tim', 'Jenny']
  1. remove():
    如果不確定該項目的index,就可以使用 remove(value) 的方式來刪除。
  2. del:
    del 是python 的陳述式,並不是list內建的 function,如果要刪除的項目是最後一個,del會釋出list物件的記憶體。
  3. pop():
    使用該項目的index做移除,如果沒有index,default為-1。

尋找index

如果我想知道 Jenny的index是多少該怎麼辦呢?
我們可以這樣寫:

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
4
print(names.index('Jenny'))
5
6
---------執行結果---------
7
4

恩!Jenny真的在[4]。

複製

我們想要複製一個list

首先來看 “ = “ 指派的方法:

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
new = names
4
print(names)
5
print(new)
6
7
---------執行結果---------
8
['Mike', 'John', 'Tim', 'Amy', 'Jenny']
9
['Mike', 'John', 'Tim', 'Amy', 'Jenny']

嗯嗯 如我們預期 new 的值跟 names 一樣。

如果我們更改 names 的值,new 會是如何?

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
new = names
4
5
names[0] = 'Faker'
6
7
print(names)
8
print(new)
9
10
---------執行結果---------
11
['Faker', 'John', 'Tim', 'Amy', 'Jenny']
12
['Faker', 'John', 'Tim', 'Amy', 'Jenny']

奇怪!我們只是更動了 names,結果 new 也更著改動了。

原因是 用 “ = “ new 只是 reference names同樣的list ,
所以 new 和 names 是用同一個list。
我們看以下 code,new 和 names 的address

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
new = names
4
print("names: ",id(names))
5
print("new: ",id(new))
6
7
---------執行結果---------
8
names:  140348091144264
9
new:  140348091144264

是一樣的!

C 語言中 variable 是一個名稱並賦予一個 memmory address
Python 卻是一個指向某個address 的 pointer

下圖為 Python variable 概念圖

那怎麼獲得一個獨立的list?
有三種方式

  1. .copy()
  2. list()轉換
  3. slice[:]
1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny']
2
3
new1 = names.copy()
4
new2 = list(names)
5
new3 = names[:]
6
7
names[0] = 'Faker'
8
9
print(names)
10
print(new1)
11
print(new2)
12
print(new3)
13
14
---------執行結果---------
15
['Faker', 'John', 'Tim', 'Amy', 'Jenny']
16
['Mike', 'John', 'Tim', 'Amy', 'Jenny']
17
['Mike', 'John', 'Tim', 'Amy', 'Jenny']
18
['Mike', 'John', 'Tim', 'Amy', 'Jenny']

大功告成!

如果list中再加入一個list看看……

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny',['GGG','zzz']]
2
new = names.copy()
3
4
names[5][0] = 'Love'
5
new[0] = 'Jake'
6
7
print(names)
8
print(new)
9
10
---------執行結果---------
11
['Mike', 'John', 'Tim', 'Amy', 'Jenny', ['Love', 'zzz']]
12
['Jake', 'John', 'Tim', 'Amy', 'Jenny', ['Love', 'zzz']]

奇怪? new 的第二層list怎麼跟著改變了,’GGG’也變成’Love’。
這個叫做 shallow copy,所謂的 shallow copy 就是只複製記憶體裡位置第一層的列表,而第二層還是有個指標指著同一個object。如下圖:

所以當 names 更改第二層 list ,new 也會跟著更改。

我們來看是不是這樣:

1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny',['GGG','zzz']]
2
new = names.copy()
3
4
# 更改 第一個元素
5
names[0]= 'xxxx'
6
7
print(id(names[0]))
8
print(id(new[0]))
9
10
#更改第二層 list
11
names[5][0] = 'love'
12
print(id(names[5]))
13
print(id(new[5]))
14
15
---------執行結果---------
16
24274016
17
19899808
18
19
24282136
20
24282136

真的是如此。

喔對了! 我發現,當我還沒更改 names[0]時,兩者第一個元素的 id 是一樣,可見 Python 等到更改時,才生一個新的address 給 new[0]。

那怎麼 copy 整份 list 呢?
我們可以使用 deep copy, import copy 模組。

1
import copy
2
3
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny',['GGG','zzz'],'gogoro']
4
5
new = copy.deepcopy(names)
6
7
print(names)
8
print(new)
9
10
print('---- 更改後 -----')
11
12
names[5][0] = 'Love'
13
new[0] = 'Lala'
14
15
print(names)
16
print(new)
17
---------執行結果---------
18
['Mike', 'John', 'Tim', 'Amy', 'Jenny', ['GGG', 'zzz'], 'gogoro']
19
['Mike', 'John', 'Tim', 'Amy', 'Jenny', ['GGG', 'zzz'], 'gogoro']
20
---- 更改後 -----
21
['Mike', 'John', 'Tim', 'Amy', 'Jenny', ['Love', 'zzz'], 'gogoro']
22
['Lala', 'John', 'Tim', 'Amy', 'Jenny', ['GGG', 'zzz'], 'gogoro']

完成了!!
但大多數情況下,不需要獨立複製一份,如果當列表夠大時,做了deepcoy()會很占記憶體空間。

排序

Python 排序的是由小到大。
Python 提供兩個 function 供我們做排序:

  1. sort(): 是 list function, 會就地排序 list 本身,也就是會更改原本的 list。
  2. sorted(): 是通用 function ,會排序list,並 return copy list,不更改原來的 list。
1
names = ['Mike', 'John', 'Tim', 'Amy', 'Jenny','gogoro']
2
print('--- sort() ----')
3
names.sort()
4
print(names)
5
6
print('--- sorted() ---')
7
names2 = ['Mike', 'John', 'Tim', 'Amy', 'Jenny','gogoro']
8
new = sorted(names2)
9
print(names2)
10
print(new)
11
---------執行結果---------
12
--- sort() ----
13
['Amy', 'Jenny', 'John', 'Mike', 'Tim', 'gogoro']
14
--- sorted() ---
15
['Mike', 'John', 'Tim', 'Amy', 'Jenny', 'gogoro']
16
['Amy', 'Jenny', 'John', 'Mike', 'Tim', 'gogoro']

呼~~~ 終於結束了

資料來源:

Python 學習筆記 系列
精通 Python:運用簡單的套件進行現代運算