5. 資料結構 - 串列, Tuple
資料結構定義
前面介紹了基本的型別, 但實際上的使用, 我們可能會有很多的物件, 例如我們可能要存放 1 到 5 的值
>>> num1 = 1
>>> num2 = 2
>>> num3 = 3
>>> num4 = 4
>>> num5 = 5
但是這樣的方式太繁雜又容易出錯, 所以有了資料結構(Data structure)的概念
List 與 Tuple
電腦中把一連串的有序資料存放起來, 我們稱為序列
基本上關於序列的資料結構我們已經在前面看過了, 其實字串就是一個只存放字元的資料結構
python 提供了串列(List)與Tuple兩種表示一序列的資料結構, 裡面可以存放任何的物件序列
而這兩種表示序列的資料結構有什麼不同?
list
是可變的, 代表宣告了之後可以任意的從中取走某個物件或插入物件
tuple
是不可變的, 宣告物件給他之後, 就無法再做更改了
其實大部分的時間都是使用 list
, 但是在一個良好的程式架構中, 我們應該要盡量用 tuple
取代 list
tuple 佔用的記憶體空間比較小
tuple 不能被修改, 對初學者來說可能覺得這是缺點, 為什麼要使用? 但是在程式架構中, 我們會有一些序列是不能夠被更動的, 所以當我們將它宣告為
tuple
後, 就能避免這件事發生函式的引數是以
tuple
傳入的
Tuple
Tuple跟costco一樣, 有人唸 costco, 另外有的人念 costco
Tuple有的人念 too-pull, 有的人念 tub-pull, 其實 python 作者是說都可以, 所以不要在意他念什麼
當我們今天要定義一個空的 tuple
時, 我們會給他一個 ()
, 而裡面為空來表示
>>> emptyTuple = ()
>>> emptyTuple
()
所以我們可能會以為用 ()
裡面放物件以後就是定義 tuple
>>> someTuple = ('stringA', 'stringB', 'stringC')
>>> someTuple
('stringA', 'stringB', 'stringC')
實際上, ,
才是他的本體, 我們也可以這樣去宣告
>>> someTuple = 'stringA', 'stringB', 'stringC'
>>> someTuple
('stringA', 'stringB', 'stringC')
>>> oneTuple = 'string',
>>> oneTuple
('string',)
>>> tupleA = ('string',)
>>> tupleA
('string',)
>>> a_str = ('string')
>>> a_str
'string'
最後一個例子, 沒有加上,
, 只有 ()
是不會被當作 tuple
的
但習慣以及可讀性上, 我們通常還是會加上
()
從位置取回值
我們將物件指派給了一個序列, 序列會為這些物件照順序給予編號, 也就是在序列中的位置(index)
這時候, 取值的方式就跟字串很像了
>>> t = ('a', 'b', 'c', 'd')
>>> t[0]
'a'
一樣使用[]
並輸入index來取回該位置的值, list
也是一樣的
指派多個變數
python 相較於大部分語言有另一個特性就是可以同時指派多個變數, 請看範例
>>> a, b, c = 1, 2, 3
>>> a
1
>>> b
2
>>> c
3
>>> (a, b, c) = (1, 2, 3)
>>> a
1
>>> b
2
>>> c
3
其實就是tuple
的一個特性, 所以我們可以這樣寫
>>> testTuple = (1, 2, 3)
>>> a, b, c = testTuple
>>> a
1
>>> b
2
>>> c
3
這種行為我們稱為tuple 開箱(unpacking)
基於這個特性, 使得 python 在交換值得時候能非常方便
>>> num1 = 15
>>> num2 = 20
>>> num1, num2 = num2, num1
>>> num1
20
>>> num2
15
這件事在大部分的程式語言可是一個經典的問題
list
我們可以用兩種方式來宣告一個空的list
>>> emptyList = []
>>> emptyList
[]
>>> emptyList2 = list()
>>> emptyList2
[]
上面有提到list()
這個函式, 其實跟之前提到過的str()
類似, 就是將()
內的東西轉型成list
>>> list('string')
['s', 't', 'r', 'i', 'n', 'g']
>>> list('aaa')
['a', 'a', 'a']
>>> aTuple = (1, 2, 3)
>>> list(aTuple)
[1, 2, 3]
另外在常用的字串應用時提到的
>>> "ab,cd,ef".spilt(',')
['ab', 'cd', 'ef']
spilt()
所回應的結果也是list
利用index更改該內容
前面提到了[]
的用法, 因為list
的特性, 使得我們可以透過index對值做修改
>>> aList = [1, 2, 3]
>>> aList
[1, 2, 3]
>>> aList[1] = 5
>>> aList
[1, 5 ,3]
>>> aList[1] = 'string'
>>> aList
[1, 'string', 3]
字串就沒辦法這麼做, 因為他是一種不可修改的序列
取一個範圍的list
同樣的, 他跟字串的[]
有類似的用法, 我們直接看範例
>>> aList = ['aa', 'bb', 'cc', 'dd', 'ee']
>>> aList[1:3]
['bb', 'cc', 'dd']
>>> aList[::2]
['aa', 'cc', 'ee']
從結尾的地方新增項目
假設我們想要加入一個新的項目, list
提供了append()
>>> aList = ['aa', 'bb', 'cc']
>>> aList.append('dd')
>>> aList
['aa', 'bb', 'cc', 'dd']
但是如果今天是一個 list
要再接另一個 list
要怎麼做, python 也有提供一街快速的方法
使用extend()
函式
>>> listOne = ['a', 'b']
>>> listTwo = ['c', 'd']
listOne.extend(listTwo)
>>> listOne
['a', 'b', 'c', 'd']
其實在之前我們有提到一個 +=
的運算, 在這裡可以直接代替extend
使用
>>> listOne = ['a', 'b']
>>> listOne += ['c', 'd']
>>> listOne
['a', 'b', 'c', 'd']
到這裡我們就要順便提一下字串串接了
前面提到過用+
來串接字串, 不過在這裡其實也可以用 +=
來串接
>>> a_str = "abc"
>>> a_str += "def"
>>> a_str
'abcdef'
其實就是同等於a_str = a_str + "def"
新增與刪除
關於list
的新增, 這裡我們直接先看範例
>>> aList = ['a', 'b', 'c']
>>> aList.insert(1, 'eee')
>>> aList
['a', 'eee', 'b', 'c']
insert
的第一個引數代表要新增的位置, 第二個代表要放入的物件
>>> aList = ['a', 'b', 'c']
>>> del aList[1]
>>> aList
['a', 'c']
del
比較特別, 他不是函式, 而是類似於=
這種陳述, 他剛好跟=
指派的動作相反, 他會將物件與名稱分離
通常我們還會使用remove
函式來做刪除
>>> aList = ['a', 'b', 'c']
>>> aList.remove('b')
>>> aList
['a', 'c']
還有一個方式,pop
能夠更快速靈活的使用, 並且將刪除的值取出來
>>> aList = ['a', 'b', 'c', 'd']
>>> aList.pop()
'd'
>>> aList
['a', 'b', 'c']
>>> aList.pop(1)
'b'
>>> aList
['a', 'c']
類似於
pop
這種函式, 他讓我們自己決定要不要帶引數,pop
假設不帶引數就是直接移除最後一個
項目是否存在
python 提供了一個方便的運算符號來讓我們知道某個值在不在資料結構中, 我們使用'in'
>>> aList = ['a', 'b', 'c']
>>> 'a' in aList
True
>>> 'd' in aList
False
當我們使用in
, 程式會回應一個布林值跟我們說有沒有辦法找到這個值
不過有時候我們不只要找到他, 還要知道他在哪一個index, 很直覺的, 我們就使用index
函式
>>> aList = ['a', 'b', 'c']
>>> aList.index('b')
1
>>> aList.index('d')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'd' is not in list
這裡忽然出現很奇怪的內容, 我們稱為例外(execption),
我們嘗試要從aList
取找'd'
, 但是其實裡面沒有這個東西, 這個函式就會沒辦法處理
通常我們軟體會崩潰(crash)也是因為出現例外, 沒有處理好
所以使用index
前我們還是要確保他是否存在
複製list
我們之前提到過, =
是指派, 而非直接複製
>>> aList = [1, 2, 3]
>>> bList = aList
>>> aList
[1, 2, 3]
>>> bList
[1, 2, 3]
>>> aList[0] = 'aa'
>>> aList
['aa', 2, 3]
>>> bList
['aa', 2, 3]
如同之前提到, =
只是將物件指派給他一個變數名稱,
當[1, 2, 3]
這個list
型態的物件被改動的時候, aList
與 bList
這兩個變數同時都是被指派[1, 2, 3]
這個物件
才會有一樣的結果
如果要複製, 我們可以使用copy
函式
>>> aList = [1, 2, 3]
>>> bList = aList.copy()
或是使用list
函式
>>> aList = [1, 2, 3]6
>>> bList = list(aList)
還可以直接這樣使用
>>> aList = [1, 2, 3]
>>> bList = aList[:]
bList = aList
與bList = aList[:]
是不一樣的,
[]
是用來取出某個位置的物件並把它獨立出來, 所以這裡也可以直接全部取出來當作複製的功用
其他應用
其他包含了len
, count
等等就不在多做介紹, 可以很簡單的找到這些用法跟範例