Python學習之路3-操作列表

VPointer發表於2019-02-16

《Python程式設計:從入門到實踐》筆記。
本章內容主要是對列表的進一步操作,以及初識元組資料結構。

1. 遍歷列表

本章主要是for迴圈:

# 程式碼:
magicians = [`alice`, `david`, `carolina`]
for magician in magicians:
    print(magician.title() + ", that was a great trick")
    print("I can`t wait to see your next trick, " + magician.title() + ".
")

print("Thank you, everyone. That was a great magic show!")

# 輸出:
Alice, that was a great trick!
I can`t wait to see your next trick, Alice.

David, that was a great trick!
I can`t wait to see your next trick, David.

Carolina, that was a great trick!
I can`t wait to see your next trick, Carolina.

Thank you, everyone. That was a great magic show!

這裡有兩個值得注意的地方,一個是“冒號”:for關鍵字所在的行最後有一個冒號;一個是縮排問題,Python中的程式碼塊都是以縮排為標準,不像C/C++,Java這樣的語言以花括號表示程式碼塊。IndentationError指縮排錯誤。

2. 建立數值列表

這有使用一個重要的生成數列的函式 range() ,以及將資料轉換成列表的 list() 函式

# 程式碼:
print(list(range(6)))         # 結束值(不包含結束值)
print(list(range(1, 6)))      # 起始值(包含),結束值(不含)
print(list(range(1, 6, 2)))   # 起始值,結束值,步長;最後一個數小於結束值
print(list(range(6, 1, -1)))  # 負數步長,此時起始值要大於結束值
print(list(range(1, 6, -1)))  # 負數步長,若起始值小於結束值,則輸出空列表

# 結果:
[0, 1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 3, 5]
[6, 5, 4, 3, 2]
[]

range()函式也常用語for迴圈,用於標識迴圈次數,或者用於生成更復雜的列表:

# 程式碼:
squares = []
for value in range(1, 11):
    squares.append(value ** 2 + 1)
print(squares)

# 結果:
[2, 5, 10, 17, 26, 37, 50, 65, 82, 101]

對於生成列表,還有一種更簡潔的寫法,即列表解析式,如上述生成列表的程式碼可以縮短為一行:

# 程式碼:
squares = [value ** 2 for value in range(1, 11)]
print(squares)

squares_2 = [value ** 2 for value in range(1, 11) if value % 2 == 0]
print(squares_2)
# 結果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[4, 16, 36, 64, 100]

列表解析式還可以更復雜,這裡就不再贅述了。

對數字列表執行簡單的統計計算
求一個數字列表的最大、最小值以及所有元素之和:

# 程式碼:
digits = list(range(10))
print(min(digits), max(digits), sum(digits))

# 結果:
0 9 45

3. 使用列表的一部分

3.1 切片

切片操作用於取原始列表的一部分:

# 程式碼:
players = [`charles`, `martina`, `michael`, `florence`, `eli`]
# [起始:結束:步長], 其中,結果列表包含起始索引,但不包含結束索引
print(players[0:3])
print(players[:3])   # 如果從0開始切片,0可以省略
print(players[1:3])
print(players[2:])   # 如果要便利到最後一個元素,結束索引可以省略,此時最後一個元素會被包含
print(players[-3:])  
print(players[::2])  # 設定了步長,但省略了結束索引,列表最後一個元素如果被遍歷到,則會被包含
print(players[:4:2]) # 設定了步長和結束索引,索引4的元素也被遍歷到了,但不會被包含在結果中

# 結果:
[`charles`, `martina`, `michael`]
[`charles`, `martina`, `michael`]
[`martina`, `michael`]
[`michael`, `florence`, `eli`]
[`michael`, `florence`, `eli`]
[`charles`, `michael`, `eli`]
[`charles`, `michael`]

切片操作的引數設定和range()函式的引數設定十分相似,起始,結束,步長都可以為負值,這裡先總結一條規律:如果步長為正數,則起始位置要在結束位置的左邊;若步長為負數,則起始位置要在結束位置的右邊。

3.2 複製列表

這裡有深淺複製的問題。如果直接將一個變數賦值到另一個變數,那麼記憶體中的資料依然只有一份,而不是兩份,這兩個變數都指向記憶體中同一個存放資料的記憶體區域,如果用C/C++的語言來描述,Python中的變數都相當於指標,這兩個變數(指標)指向的是同一片記憶體,對這兩個變數(指標)的操作會相互影響,因為都作用於同一記憶體塊,如下:

# 程式碼:
# 淺複製
players = [`charles`, `martina`, `michael`, `florence`, `eli`]
print(players)

names = players
names.append("test")
print(players)

# 結果:
[`charles`, `martina`, `michael`, `florence`, `eli`]
[`charles`, `martina`, `michael`, `florence`, `eli`, `test`]

如果想在記憶體中將原來的資料複製出一份新的,則需要深複製,切片操作則是實現深複製的一種方法:

# 程式碼:
# 深複製
players = [`charles`, `martina`, `michael`, `florence`, `eli`]
print(players)

names = players[:]
names.append("test")
print(names)
print(players)

# 結果:
[`charles`, `martina`, `michael`, `florence`, `eli`]
[`charles`, `martina`, `michael`, `florence`, `eli`, `test`]
[`charles`, `martina`, `michael`, `florence`, `eli`]

4. 元組(tuple)

和列表緊密聯絡的一個資料結構則是元組。列表非常適合用於儲存在程式執行期間可能變化的資料集,列表可以被修改。然而有時你需要建立一系列不可修改的元素,這個時候則需要用到元組。
元組用圓括號來標識,以下是宣告一個元組:

# 程式碼:
my_tuple = ()    # 空元組
one_tuple = (1,) # 宣告含有一個元素的元組。不是one_tuple = (1)

對元組中元素的訪問以及對元組的遍歷都和對列表的操作一樣;不同的是,元組中的元素不能被改變。
雖然元組中的元素不能改變,但是元組變數的值可以改變。從C/C++的角度來看,元組變數是個指標,元組相當於一個const陣列,陣列雖然不能被改變,但指標可以指向別處。

# 程式碼:
test_tuple = (1, 2, 3, 4, 5)
print(test_tuple)
test_tuple = (2, 3, 4, 5, 6)
print(test_tuple)

# 結果:
(1, 2, 3, 4, 5)
(2, 3, 4, 5, 6)

相比於列表,元組是更簡單的資料結構。如果需要儲存的一組值在程式的整個生命週期內都不變,則可使用元組。

迎大家關注我的微信公眾號”程式碼港” & 個人網站 www.vpointer.net ~

相關文章