Python 程式設計

第 11 章    串列與字組

(1) 串列簡介

∗ 串列 (List)

▸ 串列是一串 Python 的資料

▸ 串列的產生:將元素包在方括號裡,例如:

numbers = [10, 20, 30, 40]
weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'] 
aList = [10, 'Hello', 3.1415926]
emptyList = []    # 空串列  

▸ 串列裡的項目稱為元素 (Element),各個元素可以有不同的資料型態

▸ 元素也可以是另一個串列,此種串列稱為「巢狀」串列 (Nested list),例如:

nestedList = [10, 'Hello', 20.5, [30, 40]]

▸ 串列長度:最上層的元素數量

numbers = [10, 20, [30, 40, 50]]
print(len(numbers))
3

(2) 存取串列中的元素

∗ 利用索引方式取出串列元素

numbers = [10, 20, [30, 40, 50]]
print(numbers[1])
print(numbers[2])
print(numbers[2][2])
20
[30, 40, 50]
50

∗ 利用布林運算子 in 判斷是否是成員

fruits = ["apple", "orange", "banana", "cherry"]
print('apple' in fruits)
print('pear' in fruits)
print('orange' not in fruits)
True
False
False

∗ 串連 (+) 與重複 (*)

fruits = ['apple', 'orange', 'banana', 'cherry']
print([1, 2] + [3, 4])
print(fruits + [6, 7, 8, 9])
print([0]*4)
print([1, 2, ['hello', 'goodbye']]*2)
[1, 2, 3, 4]
['apple', 'orange', 'banana', 'cherry', 6, 7, 8, 9]
[0, 0, 0, 0]
[1, 2, ['hello', 'goodbye'], 1, 2, ['hello', 'goodbye']]

∗ 切片 (slice)

aList = ['a', 'b', 'c', 'd', 'e', 'f']
print(aList[1:3])    # 第 1 到第 2 個
print(aList[:4])     # 第 0 到第 3 個
print(aList[3:])     # 第 3 個到最後
print(aList[:])      # 全部
['b', 'c']
['a', 'b', 'c', 'd']
['d', 'e', 'f']
['a', 'b', 'c', 'd', 'e', 'f']

∗ 串列是可變異 (Mutable) 的資料,因此內容可修改

fruits = ['banana', 'apple', 'cherry']
print(fruits)
fruits[0] = 'pear'       # 改變第一個元素
fruits[-1] = 'orange'    # 改變最後一個元素
print(fruits)

aList = ['a', 'b', 'c', 'd', 'e', 'f'] 
aList[1:3] = ['x', 'y']    # 改變第 1 到 2 個元素
print(aList)
aList[1:3] = []    # 刪除第 1 到 2 個元素
print(aList)
['banana', 'apple', 'cherry']
['pear', 'apple', 'orange']
['a', 'x', 'y', 'd', 'e', 'f']
['a', 'd', 'e', 'f']

∗ 刪除元素或串列:del

aList = ['a', 'b', 'c', 'd', 'e', 'f']
del aList[1]    # 刪除第 1 個元素
print(aList)

del aList[1:3]  # 刪除第 1 到 2 個元素
print(aList)

del aList       # 刪除整個串列
print(aList)
['a', 'c', 'd', 'e', 'f']
['a', 'e', 'f']
NameError: name 'aList' is not defined

(3) 串列的參考

∗ 字串的參考 (Reference):變數指到 字串 物件

▸ 不同字串變數指到相同字串:字串內容分享,字串變數相同

a = 'banana'
b = 'banana'
print(a == b)
print(a is b)
True
True
reference.png

∗ 串列的參考:變數指到 串列 物件

▸ 不同串列變數指到相同內容:串列元素所指到的內容分享,但串列變數不同

a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)
print(a is b)
True
False
referenceAB.png

∗ 將串列變數指派給另一個變數

a = [1, 2, 3]
b = a         # 不同變數分享相同串列結構:此串列擁有 a 與 b 兩個「別名」(Alias)
print(a == b)
print(a is b)
b[0] = 5      # 修改某一個變數的值也會影響到另一個變數
print(a)
print(b)
True
True
[5, 2, 3]
[5, 2, 3]

assignment.png

∗ 複製串列 (Cloning):利用切片指令

a = [1, 2, 3]
b = a[:]
print(a == b)
print(a is b)
b[0] = 5      # 修改 b 的值不會影響 a
print(a)
print(b)
True
False
[1, 2, 3]
[5, 2, 3]

∗ 串列乘法

a = [1, 2]
b = [a] * 2    # 二個指向 a 的元素:[[1, 2], [1, 2]]
print(b)

a[1] = 5
print(b)
[[1, 2], [1, 2]]
[[1, 5], [1, 5]]

multiList.png

(4) 串列方法

∗ 內建串列方法

方法說明
append(<item>)在串列後端加入 <item> 項目
insert(<position>, <item>)在 <position> 位置插入 <item> 項目
pop()刪除並回覆串列的最後項目
pop(<position>)刪除並回覆串列在 <position> 位置的項目
sort()排序
reverse()反向排序
index(<item>)回覆 <item> 項目第一次出現的位置
count(<item>)回覆 <item> 項目出現的次數
remove(<item>)刪除第一次出現的 <item> 項目

∗ 範例

myList = []
myList.append(5)    # 附加
myList.append(27)
myList.append(3)
myList.append(12)
print(myList)
[5, 27, 3, 12]

myList.insert(1, 12)    # 在位置 1 插入項目
print(myList)
print(myList.count(12))    # 12 出現的次數
[5, 12, 27, 3, 12]
2

print(myList.index(3))    # 3 的位置
print(myList.count(5))    # 5 出現的次數
3
1

myList.reverse()    # 反向
print(myList)
[12, 3, 27, 12, 5]

myList.sort()    #  排序
print(myList)
[3, 5, 12, 12, 27]

myList.remove(12)  # 刪除第一個 12
print(myList)
[3, 5, 12, 27]

lastItem = myList.pop()  # 刪除並回覆最後一個項目
print(lastItem)
print(myList)
27
[3, 5, 12]

▸ 範例:產生一副撲克牌,存檔為 ch11/cards.py

✶ 構想:
# 花色 (Suite):s (Spade,黑桃),h (Heart,紅心),d (Diamond,方塊),c (Club,梅花)
# 數字 (Rank):2 ~ 14 (11:Jack, 12:Queen, 13:King, 14:Ace)
# 整副牌:s2 ~ s14, h2 ~ h14, d2 ~ d14, c2 ~ c14
import random

cards = []
for suite in ['s', 'h', 'd', 'c']:
    for rank in range(2, 15):
        cards.append(f'{suite}{rank}')

print(cards)

▸ 練習 11-1

▸ 練習 11-2

∗ 將字串分解成為串列:split()

▸ 例如:

song = "The rain in Spain..."
words = song.split()       # 預設以空白為分隔符 (Delimiter) 分解
print(words)

words = song.split('ai')   # 以 'ai' 為分隔符 (Delimiter) 分解
print(words)
['The', 'rain', 'in', 'Spain...']
['The r', 'n in Sp', 'n...']

∗ 將串列組合為字串:join()

▸ 例如:

words = ['red', 'blue', 'green']
glue = ';'
s = glue.join(words)
print(s)
print(words)

print('***'.join(words))
print(''.join(words))
red;blue;green
['red', 'blue', 'green']
red***blue***green
redbluegreen

(5) 利用迴圈處理串列

∗ for 迴圈

fruits = ['apple', 'orange', 'banana', 'cherry']
for fruit in fruits:    # 依據項目
    print(fruit)

for i in range(len(fruits)):    # 依據索引
    print(fruits[i])

for i, fruit in enumerate(fruits):    # 索引與項目並用
    print(i, fruit)

∗ 利用 for 迴圈產生串列的簡潔寫法

語法:

[<expression> for <item> in <list>]    # 無條件

[<expression> for <item> in <list> if <condition>]    # 有條件

▸ 例如:

numbers = [1, 2, 3, 4, 5]
squares = [number**2 for number in numbers]
squares2 = [number**2 for number in numbers if number%2 == 1]
print(squares)
print(squares2)
[1, 4, 9, 16, 25]
[1, 9, 25]

(6) 利用函式處理串列

∗ 透過函式修改串列

▸ 範例:函式參數 aList 是串列 numbers 的別名, 執行此函式的副作用 (Side-effect) 就是參數內容被修改了

def doubleValue(aList):
    for i in range(len(aList)):    # 將串列裡的元素都乘以 2
        numbers[i] = numbers[i] * 2


numbers = [2, 5, 9]
print(numbers)
doubleValue(numbers)
print(numbers)
[2, 5, 9]
[4, 10, 18]

▸ 純函式 (Pure function):不會產生副作用的函式,這是較好的方式

def doubleValue(aList):
    newList = []                   # 產生一個新的空白串列,不要更動參數 aList
    for value in aList:
        newList.append(2*value)    # 依據傳入參數,將元素乘 2 後附加到新串列
    return newList                 # 回覆新串列


numbers = [2, 5, 9]
print(numbers)

# 不更動原先的 numbers 串列:將結果指派給新變數 numbers2
numbers2 = doubleValue(numbers)
print(numbers2)
print(numbers)

# 將結果修改到原先串列:將結果指派給相同變數 numbers
numbers = doubleValue(numbers)
print(numbers)
[2, 5, 9]
[4, 10, 18]
[2, 5, 9]
[4, 10, 18]

(7) 字組 (Tuple)

∗ 字組 (Tuple) 與串列類似,但不可變異 (Immutable)

▸ 習慣上以小括號包住 (也可以不用),例如:

words = ('red', 'blue', 'green') 
words = 'red', 'blue', 'green'

▸ 單一項目的字組需加上逗點,否則 Python 會視括號為一般運算符號

thisIsTuple = (5, )    # 一個字組,內含一個元素 5
thisIsumber = (5)      # 數字 5

∗ 字組指派 (Tuple assignment)

▸ 可一次指派多個變數 (左右數量需相同):

employee = ('Julia', 'Roberts', 1967, 'Taichung')
(firstName, lastName, birthYear, cityLivingIn) = employee    # 指派給 4 個變數
print(firstName)
print(lastName)
print(birthYear)
print(cityLivingIn)
Julia
Roberts
1967
Taichung

▸ 換值 (Swapping)

(b, a) = (a, b)
b, a = a, b

上一章       下一章