建立數字串列
串列很適合用來存放數值集合,而Python也提供了許多工具可協助我們有效地處理數字串列。
使用 range()函式
Python 的 range()函式能很輕鬆地產生一系列的數字:
1 | for value in range(1,5): |
雖然這段程式看起來像要輸出1到5的數字,但實際上5是不會輸出的:
1 | 1 |
range()只輸出1到4的數字,這是我們常在程式語言中所看到的差 1( off-by-one )因素所造成的結果。
range()函式會讓Python從指定的第一個值開始算起,到指定的第二個值就停止,因此輸出並不含第二個值。
想要出1到5這幾個數字,要使用 range(1,6)
1 | for value in range(1,6): |
在使用range()函式時,若輸出結果不符合預期,請試著對指定的值加1或減1。
使用 range()製作數字串列
如果要製作數字串列,可使用 list()函式把 range()的結果直接轉成串列。
將 range()當成參數包在 list()中來呼叫執行,輸出的結果就會是個數字串列:
1 | numbers = list(range(1,6)) |
結果如下:
1 | [1, 2, 3, 4, 5] |
使用 range()時可以指定讓Python遞增的數值:
1 | even_numbers = list(range(2,11,2)) |
range()函式是從2開始起算,以2來,直到或超過第二個數值11才停止:
1 | [2, 4, 6, 8, 10] |
使用 range()函式幾乎可以製作任何數字集,
製作存放一個1到10的平方值的串列,在Python中用兩個星號( ** )來表示乘方的運算:
1 | squares = [] |
首先建立空串列,接著使用 range()函式讓Python 以迴圈遍訪1到10的整數值,
將在迴圈內的運算結果存入 square變數內,並使用 append()方法把每個平方值新增到 squares串列尾端,
最後在迴圈結束後輸出 squares串列:
1 | [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] |
也可以用更簡潔的方式得到相同的運算結果:
1 | squares = [] |
數字串列的簡單統計運算
Python中有幾個函式可專門用來高數字串列的運算:
1 | >>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] |
串列推導解析
前面描述的製作 squares 串列的方式用了三到四行程式碼,
而串列推導解析( list comprehension )則讓我們只用一行程式製作相同的串列。
串列推導解析把 for 迴圈和建立新元素的程式碼合併成一行,並自動地新增每個新的元素:
1 | squares = [ value ** 2 for value in range(1,11)] |
請留意這裡的 for 陳述句尾端並沒有冒號哦!
處理串列中某部份的內容
我們還可只處理串列中某部份的內容,在Python 中稱之為「切片( slice )」
切片
切片需要指定使用的第一個元素和最後一個元素的索引足標。
與 range()函式相同,Python 在算到指定的第二個索引足標前的元素就會停止,
所以處理範圍不含第二個索引足標的元素:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
此切片有三名隊員,輸出的結果也是個串列:
1 | ['charles', 'martina', 'michael'] |
若想擷取串列中第2到第4個元素,就把切片的起始索引足標設為1,結尾索引足標設為4:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
結果如下:
1 | ['martina', 'michael', 'florence'] |
如果沒有指定第一個索引足標,Python 會自動以串列的開頭為切片的起始:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
結果如下:
1 | ['charles', 'martina', 'michael', 'florence'] |
也有類似的作法讓切片可擷取到串列結尾:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
Python 會返回串列從第三個到結尾的所有項目元素:
1 | ['michael', 'florence', 'eli'] |
此外也可以使用負數來當索引足標,負數是從尾端往回推的距離,因此可取出串列任意尾段的切片:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
這段程式會輸出串列到數後三名的元素項目,就算串列長度有變化也不影響。
迴圈遍訪切片
若想以迴圈遍訪串列某部份的項目元素,可在 for 迴圈中使用切片來達成:
1 | players = ['charles', 'martina', 'michael', 'florence', 'eli'] |
for 迴圈並沒有遍訪整個 players 串列,Python 只遍訪串列的前三項:
1 | Here are the first three players on my team: |
複製串列
在編寫程式時,很常需要以現在的串列為基礎來建立全新的串列。
若想要複製串列,可以先建立一個含有原本整個串列的切片,其做法就是都不放起始和結尾索引足標,
只留一個冒號在中括號內( [:] ),這樣就能複製整個串列了:
1 | my_foods = ['pizza,', 'falafel', 'carrot cake'] |
不指定索引足標的方法從 my_foods 串列擷取整個串列當切片,等於複製了這個串列並指定到 friend_foods 變數內:
1 | My favorite foods are: |
可以分別新增不同食物到各自的串列內,確定這兩個串列都存放了自己和朋友最喜歡的食物:
1 | my_foods = ['pizza,', 'falafel', 'carrot cake'] |
將 my_foods 與 複製出來的 friend_foods 兩個串列分別新增新的項目進去,最後輸出兩個串列:
1 | My favorite foods are: |
假如只是單純地把 my_foods 指定給 friend_foods ( friend_foods = my_foods ),
這樣並不會真的建立兩個串列:
1 | my_foods = ['pizza,', 'falafel', 'carrot cake'] |
這樣並不是把 my_foods 的複製品指定存入 friend_foods。
這種指定語法在 Python 中是讓新的 friend_foods 變數連接到 my_foods 已存放的串列上,
兩個變數都指向同一個串列:
1 | My favorite foods are: |
這樣的輸出結果並不是我們所要的。
多元組
有時候相要建立一個不能被修改的資料集合,這時「多元組( tuples,或元組 )」能滿足這項要求。Python 把不能修改的值稱為不可變的( immutable ),而這個不可變的串列就稱為多元組。
定義多元組
多元組看起來很像串列,但用的是小括號( () )而不是中括號( [] )來定義標示。
在定義完多元組之後就可以用項目的索引足標來提取其中的元素,作法和串列相同:
1 | dimensions = (200, 50) |
使用小括號定義多元組後,再將每個項目分別輸出,使用的語法和存取串列中的元素是一樣的:
1 | 200 |
試著修改多元組中的任一元素會有什麼結果:
1 | dimensions = (200, 50) |
試著修改多元組中的第一個項目的值,結果如下:
1 | Traceback (most recent call last): |
因為修改多元組是不允許的,所以Python會告知不能對多元組中的項目指定新值。
遍訪多元組中所有的值
就像在處理串列一樣,可以使用 for 迴圈遍訪多元組中所有的值:
1 | dimensions = (200, 50) |
結果與串列一樣,Python會返回多元組中所有的元素
1 | 200 |
重寫多元組
雖然不能修改多元組,但卻可以把新的值指定給存放多元組的變數內:
1 | dimensions = (200, 50) |
執行後Python 沒有回報錯誤訊息,因為重寫多元組並指定到變數是合法的:
1 | Original dimensions: |
與串列相比,多元組算是簡單的資料結構。
如果在程式的整個生命週期中想要存放一組都不會改變的值,就很適合用多元組來定義。