Python 101 基礎教學 (7) - Collections:list、tuple

以下要介紹的資料型態是容器類型的 list 與 tuple。容器類型意指它們是可以裝其他資料的資料。每種資料型態,都有不同的目的,在適當時機使用不同的資料型態可以發揮最好的效果。

串列 List

最基本的容器類型,把多筆資料有順序的擺在一起。可以對 list 做一些基本操作,像是查找、新增、插入、修改、刪除還有讀取等等。Python的list跟其他語言的list或array比起來有著相當強大的優勢,有很多"pythonic"的用法,讓你在語法上簡潔很多!

要知道在做不同的操作時,底層所花費的時間也不一樣,其中插入、修改、刪除這些操作需要"掃描"整個 list (或部分),所需成本比較高,後面如果有講解時間複雜度會更細節講解。

讀取 list 不會修改本身,可以讀取單一資料,也能一次讀取範圍資料。

a = [1, 2, 3, 4]
print(a) # output: [1, 2, 3, 4]

# 題外話: list 可以裝不同類型的資料,大部分情況不建議
x = [1, [2, 3], (1, 2), '234', None, false] # It works!!

# 讀取個別資料(讀取不會修改list)
# 藉由索引(index)去讀取資料,從0開始為第一個
print(a[0]) # output: 1
print(a[1]) # output: 2
print(a[3]) # output: 4
print(a[4]) # IndexError: list index out of range

# 可以用負的索引讀取
print(a[-1]) # output: 4 (-1 為讀取最後一個)
print(a[-2]) # output: 3

# 讀取部分資料: arr_name[begin:end:step]
# 拿到的list視為新的list,不會改變原本的list a
print(a[1:3]) # output: [2, 3] (從index 1讀到index 3但不包含index 3本身)
print(a[1:]) # output: [2, 3, 4] (從index 1讀到最後)
print(a[:1]) # output: [1] (從第一個(index 0)讀到index 1但不包含index 1本身)
print(a[:]) # output: [1, 2, 3, 4] (=a[0:4], 可以理解為複製一個list)
print(a[-2:]) # output: [3, 4] (從倒數第二個讀到最後)
print(a[-2:-1]) # output: [3] (從倒數第二個讀到最後倒數第一個但不包含)
print(a[-2:-3]) # output: [] (無法往前讀,所以拿不到東西)

print(a[::2]) # output: [1, 3] (=a[0:4:2], step為2指的是每次index+2去讀取)
print(a[::-1]) # output: [4, 3, 2, 1] (step為-1, 倒著讀取)

# 解構型讀取
a = [1, 2]
x, y = a # x = 1, y = 2

a = [1, 2, 3]
x, y = a 
# 數量不一樣時會報錯
# ValueError: too many values to unpack (expected 2)

會改變 list 本身的操作包含了新增、插入、修改、刪除等。

a = [1, 2, 3]

''' 
新增
'''
a.append(4) # a = [1, 2, 3, 4] (在後面新增一筆新資料)
b = [5, 6]
a.extend(b) # a = [1, 2, 3, 4, 5, 6] (在a後面接上另一組list b)

# note: print(a.append(...)) 會output None
# `append`只做新增的操作不返回值,需要a.append(...)然後下一行print(a)

'''
修改
'''
a[0] = 0 # a = [0, 2, 3, 4, 5, 6] 
a[-2] = 6 # a = [0, 2, 3, 4, 6, 6]

a[1:3] = [8, 9, 10] 
# a = [0, 8, 9, 10, 4, 6, 6]
# 以上a[1:3] = [2, 3]=>把[2, 3]替換成[8, 9, 10]

'''
插入: arr_name.insert(index, data)
'''
a.insert(0, 100) 
# 在index 0的位置插入資料100
# a = [100, 0, 8, 9, 10, 4, 6, 6]

'''
刪除 remove/pop
'''
animals = ['dog', 'cat', 'dog', 'bird', 'pig', 'rabbit']

# remove是依據指定data去移除: arr_name.remove(data)
# remove不返回資料 (print的話會是None)
animals.remove('dog')
# animals = ['cat', 'dog', 'bird', 'pig', 'rabbit']
# 以上remove會移除第一個找到的dog

animals.remove('fish')
# 以上會移除不存在的東西會報錯:ValueError: list.remove(x): x not in list

# pop是依據index去移除data: arr_name.pop(index)
# pop會返回被移除的資料
animals.pop(2) 
# return 'bird'
# animals = ['cat', 'dog', 'pig', 'rabbit']

還可以做 list 的查找動作。

a = [1, 3, 3, 5, 6]

'''
使用in判斷是否資料在list裡
'''
print(1 in a) # output: True (是否list a 裡包含 1)
print(2 in a) # output: False

'''
使用index找出資料在list裡的位置
'''
print(a.index(1)) # ouptut: 0 (資料1在index 0的位置)
print(a.index(3)) # ouptut: 1 (回傳第一個match到的位置,所以得到index 1)
print(a.index(2)) # 2不在list裡所以會報錯:ValueError: 2 is not in list

# 查到動作可以用於Iterable的資料類型,意味著也可以把以上方法用在str上
s = '123'
print('1' in s) # output: True
print(s.index('2')) # output: 1

Tuple

tuple 與 list 是大同小異,差異就在於 tuple 資料在建立之後就無法改動了,而 list 可以。

a = (1, 2, 3)
print(a) # output: (1, 2, 3)

a = (1,) # 如果要宣告只有一筆資料的tuple要使用這種寫法
a = (1) # a = 1, 這不是tuple

'''
讀取:用法與list基本相同
'''
print(a[0]) # output: 1
print(a[1:]) # output: (2, 3)

'''
無法修改
'''
a[0] = 4 
# TypeError: 'tuple' object does not support item assignment

a = (1, [2, 3])
a[1][2] = 4
print(a) # output: (1, [2, 4])
# 以上可以修改,因為改的是tuple裡的list不是tuple本身

實際操作

了解了一些 list 與 tuple 的觀念,當然 list 與 tuple 還有很多實用的 function 可以搭配使用,例如min, len, count 等等。加上迴圈(for loop/while),我們就可以結合使用做出很多不同的變化去處理資料。

'''
找出list裡最小值
'''
a = [1, 3, 6, 0, -1, 100]
print(min(a)) # output: -1


'''
用for loop找出list裡最小值 
'''
a = [1, 3, 6, 0, -1, 100]
minimum = float('inf') # float('inf') 代表無限大
for elem in a:
    if minimum > elem:
        minimum = elem

print(minimum)
# 以上與`min`函式如果遇到空list的話,需要另外處理,這裡只是演示範例


'''
算出list長度
'''
a = [1, 2, 3]
print(len(a)) # output: 3


'''
統計list裡某項元素個數
'''
a = [1, 2, 1, 3, 1]
print(a.count(1)) # output: 3 (list a裡有3個1)


'''
使用for loop複製list (當然你可以直接使用x[:], 這邊只是例子)
'''
a = [1, 2, 3]
b = []
for elem in a:
    b.append(elem)

print(b) # output: [1, 2, 3]


'''
list加總
'''
a = [1, 3, 5, 7, 9]
print(sum(a)) # output: 25


'''
用for loop 計算list加總
'''
a = [1, 3, 5, 7, 9]
total = 0
for elem in a:
    total += elem

print(total)  # output: 25

以上只是一些基礎用法,list/tuple還有非常多的觀念及用法,像是list comprehension 等,有了概念以後隨時參考官方文檔,會用得越多就越事半功倍。

繼續閱讀:

Python 101 基礎教學 (8) - Collections:set、dictionary
這篇想要介紹另外兩個資料型態:set 與 dictionary。這兩個類型的存在與 list 比較,更具效能的優勢。用 set/dict 在查找資料時,大部分情況都是不需要做”掃描”的動作。