3.1 清單是什麼
清單 由一系列按特定順序排列的元素組成。你可以建立包含字母表中所有字母、數字0~9或所有家庭成員姓名的清單;也可以将任何東西加入清單中,其中的元素之間可以沒有 任何關系。鑒于清單通常包含多個元素,給清單指定一個表示複數的名稱(如letters 、digits 或names )是個不錯的主意。
在Python中,用方括号([] )來表示清單,并用逗号來分隔其中的元素。下面是一個簡單的清單示例,這個清單包含幾種自行車:
bicycles.py
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)
如果你讓Python将清單列印出來,Python将列印清單的内部表示,包括方括号: ['trek', 'cannondale', 'redline', 'specialized']
鑒于這不是你要讓使用者看到的輸出,下面來學習如何通路清單元素。
3.1.1 通路清單元素
清單是有序集合,是以要通路清單的任何元素,隻需将該元素的位置或索引告訴Python即可。要通路清單元素,可指出清單的名稱,再指出元素的索引,并将其放在方括号内。 例如,下面的代碼從清單bicycles 中提取第一款自行車:
bicycles = ['trek', 'cannondale', 'redline', 'specialized'] ❶ print(bicycles[0])
❶處示範了通路清單元素的文法。當你請求擷取清單元素時,Python隻傳回該元素,而不包括方括号和引号:
trek
這正是你要讓使用者看到的結果——整潔、幹淨的輸出。
你還可以對任何清單元素調用第2章介紹的字元串方法。例如,可使用方法title() 讓元素'trek' 的格式更整潔: bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0].title())
這個示例的輸出與前一個示例相同,隻是首字母T是大寫的。
3.1.2 索引從0而不是1開始
在Python中,第一個清單元素的索引為0,而不是1。在大多數程式設計語言中都是如此,這與清單操作的底層實作相關。如果結果出乎意料,請看看你是否犯了簡單的差一錯誤。 第二個清單元素的索引為1。根據這種簡單的計數方式,要通路清單的任何元素,都可将其位置減1,并将結果作為索引。例如,要通路第四個清單元素,可使用索引3。
下面的代碼通路索引1 和3 處的自行車:
bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles[1])
print(bicycles[3])
這些代碼傳回清單中的第二個和第四個元素:
cannondale
specialized
Python為通路最後一個清單元素提供了一種特殊文法。通過将索引指定為-1 ,可讓Python傳回最後一個清單元素:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[-1])
這些代碼傳回'specialized' 。這種文法很有用,因為你經常需要在不知道清單長度的情況下通路最後的元素。這種約定也适用于其他負數索引,例如,索引-2 傳回倒數第 二個清單元素,索引-3 傳回倒數第三個清單元素,以此類推。
3.1.3 使用清單中的各個值
可像使用其他變量一樣使用清單中的各個值。例如,你可以使用拼接根據清單中的值來建立消息。 下面來嘗試從清單中提取第一款自行車,并使用這個值來建立一條消息:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
❶ message = "My first bicycle was a " + bicycles[0].title() + "."
print(message)
我們使用bicycles[0] 的值生成了一個句子,并将其存儲在變量message 中(見❶)。輸出是一個簡單的句子,其中包含清單中的第一款自行車: My first bicycle was a Trek.
動手試一試
請嘗試編寫一些簡短的程式來完成下面的練習,以獲得一些使用Python清單的第一手經驗。你可能需要為每章的練習建立一個檔案夾,以整潔有序的方式存儲為完成各 章的練習而編寫的程式。
3-1 姓名: 将一些朋友的姓名存儲在一個清單中,并将其命名為names 。依次通路該清單中的每個元素,進而将每個朋友的姓名都列印出來。
3-2 問候語: 繼續使用練習3-1中的清單,但不列印每個朋友的姓名,而為每人列印一條消息。每條消息都包含相同的問候語,但擡頭為相應朋友的姓名。
3-3 自己的清單: 想想你喜歡的通勤方式,如騎機車或開汽車,并建立一個包含多種通勤方式的清單。根據該清單列印一系列有關這些通勤方式的宣言,如“I would like to own a Honda motorcycle”。
3.2 修改、添加和删除元素
你建立的大多數清單都将是動态的,這意味着清單建立後,将随着程式的運作增删元素。例如,你建立一個遊戲,要求玩家射殺從天而降的外星人;為此,可在開始時将一些外
星人存儲在清單中,然後每當有外星人被射殺時,都将其從清單中删除,而每次有新的外星人出現在螢幕上時,都将其添加到清單中。在整個遊戲運作期間,外星人清單的長度
将不斷變化。
3.2.1 修改清單元素
修改清單元素的文法與通路清單元素的文法類似。要修改清單元素,可指定清單名和要修改的元素的索引,再指定該元素的新值。 例如,假設有一個機車清單,其中的第一個元素為'honda' ,如何修改它的值呢?
motorcycles.py
❶ motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles)
❷ motorcycles[0] = 'ducati' print(motorcycles)
我們首先定義一個機車清單,其中的第一個元素為'honda' (見❶)。接下來,我們将第一個元素的值改為'ducati' (見❷)。輸出表明,第一個元素的值确實變了,但 其他清單元素的值沒變:
['honda', 'yamaha', 'suzuki']
['ducati', 'yamaha', 'suzuki']
你可以修改任何清單元素的值,而不僅僅是第一個元素的值。
3.2.2 在清單中添加元素
你可能出于衆多原因要在清單中添加新元素,例如,你可能希望遊戲中出現新的外星人、添加可視化資料或給網站添加新注冊的使用者。Python提供了多種在既有清單中添加新資料
的方式。
1. 在清單末尾添加元素
在清單中添加新元素時,最簡單的方式是将元素附加到清單末尾。給清單附加元素時,它将添加到清單末尾。繼續使用前一個示例中的清單,在其末尾添加新元素'ducati' :
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
❶ motorcycles.append('ducati') print(motorcycles)
方法append() 将元素'ducati' 添加到了清單末尾(見❶ ),而不影響清單中的其他所有元素:
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha', 'suzuki', 'ducati']
方法append() 讓動态地建立清單易如反掌,例如,你可以先建立一個空清單,再使用一系列的append() 語句添加元素。下面來建立一個空清單,再在其中添加元 素'honda' 、'yamaha' 和'suzuki' :
motorcycles = []
motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')
print(motorcycles)
最終的清單與前述示例中的清單完全相同: ['honda', 'yamaha', 'suzuki']
這種建立清單的方式極其常見,因為經常要等程式運作後,你才知道使用者要在程式中存儲哪些資料。為控制使用者,可首先建立一個空清單,用于存儲使用者将要輸入的值,然後将 使用者提供的每個新值附加到清單中。
2. 在清單中插入元素
使用方法insert() 可在清單的任何位置添加新元素。為此,你需要指定新元素的索引和值。
motorcycles = ['honda', 'yamaha', 'suzuki']
❶ motorcycles.insert(0, 'ducati') print(motorcycles)
在這個示例中,值'ducati' 被插入到了清單開頭(見❶);方法insert() 在索引0 處添加空間,并将值'ducati' 存儲到這個地方。這種操作将清單中既有的每個元素都右
移一個位置:
['ducati', 'honda', 'yamaha', 'suzuki']
3.2.3 從清單中删除元素
你經常需要從清單中删除一個或多個元素。例如,玩家将空中的一個外星人射殺後,你很可能要将其從存活的外星人清單中删除;當使用者在你建立的Web應用中登出其賬戶時, 你需要将該使用者從活躍使用者清單中删除。你可以根據位置或值來删除清單中的元素。
1. 使用del 語句删除元素
如果知道要删除的元素在清單中的位置,可使用del 語句。
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
❶ del motorcycles[0]
print(motorcycles)
❶ 處的代碼使用del 删除了清單motorcycles 中的第一個元素——'honda' : ['honda', 'yamaha', 'suzuki']
['yamaha', 'suzuki']
使用del 可删除任何位置處的清單元素,條件是知道其索引。下例示範了如何删除前述清單中的第二個元素——'yamaha' :
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
del motorcycles[1]
print(motorcycles)
下面的輸出表明,已經将第二款機車從清單中删除了:
['honda', 'yamaha', 'suzuki']
['honda', 'suzuki']
在這兩個示例中,使用del 語句将值從清單中删除後,你就無法再通路它了。
2. 使用方法pop() 删除元素
有時候,你要将元素從清單中删除,并接着使用它的值。例如,你可能需要擷取剛被射殺的外星人的 x 和 y 坐标,以便在相應的位置顯示爆炸效果;在Web應用程式中,你可能 要将使用者從活躍成員清單中删除,并将其加入到非活躍成員清單中。
方法pop() 可删除清單末尾的元素,并讓你能夠接着使用它。術語彈出 (pop)源自這樣的類比:清單就像一個棧,而删除清單末尾的元素相當于彈出棧頂元素。 下面從清單motorcycles 中彈出一款機車:
❶ motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles)
❷ popped_motorcycle = motorcycles.pop() ❸ print(motorcycles)
❹ print(popped_motorcycle)
我們首先定義并列印了清單motorcycles (見❶)。接下來,我們從這個清單中彈出一個值,并将其存儲到變量popped_motorcycle 中(見❷)。然後我們列印這個列 表,以核實從其中删除了一個值(見❸)。最後,我們列印彈出的值,以證明我們依然能夠通路被删除的值(見❹)。
輸出表明,清單末尾的值'suzuki' 已删除,它現在存儲在變量popped_motorcycle 中:
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha']
suzuki
方法pop() 是怎麼起作用的呢?假設清單中的機車是按購買時間存儲的,就可使用方法pop() 列印一條消息,指出最後購買的是哪款機車: motorcycles = ['honda', 'yamaha', 'suzuki']
last_owned = motorcycles.pop()
print("The last motorcycle I owned was a " + last_owned.title() + ".")
輸出是一個簡單的句子,指出了最新購買的是哪款機車: The last motorcycle I owned was a Suzuki.
3. 彈出清單中任何位置處的元素
實際上,你可以使用pop() 來删除清單中任何位置的元素,隻需在括号中指定要删除的元素的索引即可。
motorcycles = ['honda', 'yamaha', 'suzuki']
❶ first_owned = motorcycles.pop(0)
❷ print('The first motorcycle I owned was a ' + first_owned.title() + '.')
首先,我們彈出了清單中的第一款機車(見❶),然後列印了一條有關這輛機車的消息(見❷)。輸出是一個簡單的句子,描述了我購買的第一輛機車: The first motorcycle I owned was a Honda.
别忘了,每當你使用pop() 時,被彈出的元素就不再在清單中了。
如果你不确定該使用del 語句還是pop() 方法,下面是一個簡單的判斷标準:如果你要從清單中删除一個元素,且不再以任何方式使用它,就使用del 語句;如果你要在删除元 素後還能繼續使用它,就使用方法pop() 。
4. 根據值删除元素
有時候,你不知道要從清單中删除的值所處的位置。如果你隻知道要删除的元素的值,可使用方法remove() 。 例如,假設我們要從清單motorcycles 中删除值'ducati' 。
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] print(motorcycles)
❶ motorcycles.remove('ducati') print(motorcycles)
❶ 處的代碼讓Python确定'ducati' 出現在清單的什麼地方,并将該元素删除: ['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']
使用remove() 從清單中删除元素時,也可接着使用它的值。下面删除值'ducati' ,并列印一條消息,指出要将其從清單中删除的原因:
❶ motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
❷ too_expensive = 'ducati'
❸ motorcycles.remove(too_expensive) print(motorcycles)
❹ print("\nA " + too_expensive.title() + " is too expensive for me.")
在❶處定義清單後,我們将值'ducati' 存儲在變量too_expensive 中(見❷)。接下來,我們使用這個變量來告訴Python将哪個值從清單中删除(見❸)。最後,
值'ducati' 已經從清單中删除,但它還存儲在變量too_expensive 中(見❹),讓我們能夠列印一條消息,指出将'ducati' 從清單motorcycles 中删除的原因:
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']
A Ducati is too expensive for me.
>
注意 方法remove() 隻删除第一個指定的值。如果要删除的值可能在清單中出現多次,就需要使用循環來判斷是否删除了所有這樣的值。你将在第7章學習如何這
樣做。
cars.py
cars = ['bmw', 'audi', 'toyota', 'subaru']
❶ cars.sort()
print(cars)
方法sort() (見❶)永久性地修改了清單元素的排列順序。現在,汽車是按字母順序排列的,再也無法恢複到原來的排列順序:
['audi', 'bmw', 'subaru', 'toyota']
你還可以按與字母順序相反的順序排列清單元素,為此,隻需向sort() 方法傳遞參數reverse=True 。下面的示例将汽車清單按與字母順序相反的順序排列: cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)
print(cars)
同樣,對清單元素排列順序的修改是永久性的: ['toyota', 'subaru', 'bmw', 'audi']
3.3.2 使用函數sorted() 對清單進行臨時排序
要保留清單元素原來的排列順序,同時以特定的順序呈現它們,可使用函數sorted() 。函數sorted() 讓你能夠按特定順序顯示清單元素,同時不影響它們在清單中的原始排
列順序。
下面嘗試對汽車清單調用這個函數。
cars = ['bmw', 'audi', 'toyota', 'subaru']
❶ print("Here is the original list:")
print(cars)
❷ print("\nHere is the sorted list:") print(sorted(cars))
❸ print("\nHere is the original list again:")
print(cars)
我們首先按原始順序列印清單(見❶),再按字母順序顯示該清單(見❷)。以特定順序顯示清單後,我們進行核實,确認清單元素的排列順序與以前相同(見❸)。
Here is the original list:
['bmw', 'audi', 'toyota', 'subaru']
Here is the sorted list:
['audi', 'bmw', 'subaru', 'toyota']
❹ Here is the original list again:
['bmw', 'audi', 'toyota', 'subaru']
注意,調用函數sorted() 後,清單元素的排列順序并沒有變(見❹)。如果你要按與字母順序相反的順序顯示清單,也可向函數sorted() 傳遞參數reverse=True 。
注意 在并非所有的值都是小寫時,按字母順序排列清單要複雜些。決定排列順序時,有多種解讀大寫字母的方式,要指定準确的排列順序,可能比我們這裡所做的 要複雜。然而,大多數排序方式都基于本節介紹的知識。
3.3.3 倒着列印清單
要反轉清單元素的排列順序,可使用方法reverse() 。假設汽車清單是按購買時間排列的,可輕松地按相反的順序排列其中的汽車: cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)
cars.reverse()
print(cars)
注意,reverse() 不是指按與字母順序相反的順序排列清單元素,而隻是反轉清單元素的排列順序: ['bmw', 'audi', 'toyota', 'subaru']
['subaru', 'toyota', 'audi', 'bmw']
方法reverse() 永久性地修改清單元素的排列順序,但可随時恢複到原來的排列順序,為此隻需對清單再次調用reverse() 即可。
3.3.4 确定清單的長度
使用函數len() 可快速獲悉清單的長度。在下面的示例中,清單包含4個元素,是以其長度為4: >>> cars = ['bmw', 'audi', 'toyota', 'subaru']
>>> len(cars)
4
在你需要完成如下任務時,len() 很有用:确定還有多少個外星人未被射殺,需要管理多少項可視化資料,網站有多少注冊使用者等。
注意 Python計算清單元素數時從1開始,是以确定清單長度時,你應該不會遇到差一錯誤。
3.4 使用清單時避免索引錯誤
剛開始使用清單時,經常會遇到一種錯誤。假設你有一個包含三個元素的清單,卻要求擷取第四個元素: motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles[3])
這将導緻索引錯誤 :
Traceback (most recent call last):
File "motorcycles.py", line 3, in <module> print(motorcycles[3])
IndexError: list index out of range
Python試圖向你提供位于索引3處的元素,但它搜尋清單motorcycles 時,卻發現索引3處沒有元素。鑒于清單索引差一的特征,這種錯誤很常見。有些人從1開始數,是以以為 第三個元素的索引為3;但在Python中,第三個元素的索引為2,因為索引是從0開始的。
索引錯誤意味着Python無法了解你指定的索引。程式發生索引錯誤時,請嘗試将你指定的索引減1,然後再次運作程式,看看結果是否正确。
别忘了,每當需要通路最後一個清單元素時,都可使用索引-1 。這在任何情況下都行之有效,即便你最後一次通路清單後,其長度發生了變化:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles[-1])
索引-1 總是傳回最後一個清單元素,這裡為值'suzuki' :
'suzuki'
僅當清單為空時,這種通路最後一個元素的方式才會導緻錯誤:
motorcycles = []
print(motorcycles[-1])
清單motorcycles 不包含任何元素,是以Python傳回一條索引錯誤消息:
Traceback (most recent call last):
File "motorcyles.py", line 3, in <module> print(motorcycles[-1])
IndexError: list index out of range
注意 發生索引錯誤卻找不到解決辦法時,請嘗試将清單或其長度列印出來。清單可能與你以為的截然不同,在程式對其進行了動态處理時尤其如此。通過檢視清單 或其包含的元素數,可幫助你找出這種邏輯錯誤。