- Python程序設計
- 張雪萍主編
- 3242字
- 2019-06-19 15:48:27
2.3 列表
2.3.1 列表基本特征
前面已經介紹完數字類型,其通常只處理單個元素對象,而在實際開發過程中經常會將一系列對象并列放在一起形成一個集合來進行操作,或者形成數據結構,這就是接下來要講的序列。
序列描述了數據類型的一種形態,具體的數據類型有很多,包括列表、元組、字符串,這些都屬于序列類型。
從特性上來講它可以分為兩類,一類是可變序列,另一類是不可變序列。
可變序列:序列中的某個元素支持在原位置被改變。
不可變序列:不允許在原位置改變某個元素或對象的值。
首先來看可變序列中使用頻率最高的列表。列表可以說是Python語言中使用頻率最高的一個有序序列(這里的有序指的是先后順序而不是大小順序)。
1.列表的定義
列表(list):可以包含任意對象的有序集合(可以包含類型統一的整數,也可以包含不同類型的如串、元組、字典、自己定義的類等,并且它是有序的,順序是可以自定義的)。
2.列表的聲明
來看處理學生成績的例子,當處理一個學生一門課程的成績時,可以通過定義一個變量來保存成績。如果要處理很多門課程的成績,當然也可以定義多個變量來保存成績,但它們是一個有機的整體或在邏輯上有一定的關系,此時可以把它們組織到一個數據結構里,這就是列表。

列表的聲明:列表用一對中括號來聲明,中括號里寫上多個元素,中間以逗號隔開,逗號是默認的分隔符,這些元素可以是任意類型的數據。
3.列表的特性
列表具有以下特性:
(1)可以包含任意對象的有序集合,如x=[89,90.3,'tom']。
(2)可以通過下標索引來訪問 list 中的某個元素。下標索引從左邊開始時總是從 0開始,而從右邊開始時,就從-1開始。序列類型的索引體系如圖2-1所示。

圖2-1 序列類型的索引體系
(3)可變長度(可任意增減元素);異質(可包含任意類型的元素);可任意嵌套(列表的元素也可以是一個列表)。
(4)支持原位改變,如x=[89,90.3,'tom'],支持x[0]=99這樣的操作。


注意:上例中,對列表中的元素又是一個列表的情況,可以通過 x[3]獲得列表[56,89,89],接下來想對值 56 進行訪問,那就按照下標索引的方式對其進行訪問操作,因此獲取值56的表達式為x[3][0]。
4.列表轉換函數list()
通過列表轉換函數list()可以將某個特定的可迭代序列轉換為列表。

2.3.2 序列通用操作
列表屬于可變序列,也是Python中使用頻率最高、最通用的數據類型。序列類型有很多,除了列表,后面還會介紹元組及字符串。下面先介紹序列通用操作,還是以 list為例。
在講序列的通用操作之前,先介紹列表的初始化。列表的初始化可以通過中括號來直接設定元素列表。
1.列表的初始化
列表用中括號將若干元素括起來,中間用逗號分隔。

2.序列的通用操作——以列表為例
序列的通用操作包括判斷元素是否在序列之內、序列連接、重復序列元素等,詳細說明如表2-7所示。
表2-7 序列通用操作

續表

關于通用操作的幾點說明。
1)切片操作

觀察上面的結果,當步長是一個負數時,是從后向前按步長的絕對值取出元素的,如果步長是-1,則得到的是一個置逆的結果。同樣要注意的是,這里是對列表中的元素進行訪問,訪問操作本身并不改變列表的值。上面最后一行代碼輸出的結果是 2 和 4,并沒有因為x[::-1]操作得到一個置逆的結果并改變原列表,所以,輸出的并不是5和3。
下面用一個示例來解釋列表的兩個下標索引 [2]。

索引可以理解為是放在兩個元素中間的縫隙中的,讀取它的值時是讀取它之后的值。這樣對于范圍如[0:2],表示的是0~2(包括0但不包括2)的那些元素值。


注意:獲取列表元素的值時,下標不能越界!
只有當后面右側有內容的時候,前面的索引才會起作用。
下標索引的使用也可以從后往前即從-1 開始,但當有兩個下標索引時,同樣最后一個索引對象的值不包含在內。例如:

以上結果表明,列表x和y并未指向同一個對象,它們不屬于共享引用。
3)求和操作sum(ls)
如果想統計序列中元素的總和,可以用全局函數“sum”來實現,注意 sum 求和操作只針對序列元素是數字類型的情況。


由于列表是序列的一種,而序列除了列表還有其他的一些類型,在介紹其他的類型及列表的操作之前,應先了解所有序列通用的操作,這些操作使用都很方便。但是我們要分辨一下這些操作哪些是通過函數來完成的,哪些是通過方法來完成的。方法是與某個對象相互關聯的,它的調用方式是對象名.方法名()。函數的調用方式是函數名(參數表),函數分為全局函數和來自某個模塊的特定的函數[3]。
2.3.3 可變序列及列表通用操作(一)
雖然列表是可變序列,但前面以列表為例介紹的通用操作同樣適用于不可變序列。
下面將繼續以列表為例來介紹可變序列的通用操作。這些操作既可以作用到列表上,也可以作用到其他可變序列的數據結構上。表2-8列出了可變序列及列表的通用操作。
表2-8 可變序列及列表的通用操作(一)



s[:3]=100是不被允許的。因為這里有歧義,究竟是希望把前3個值刪掉,然后插入一個100呢?還是要把前3個值每個都換成100呢?不能確定,因此,系統拒絕這樣的操作。

此時需要注意:如果使用開始加終止索引,并且指定了步長值,那么在給它賦值的時候,除了必須要給它一個可迭代的對象,還必須清楚它共有幾個值會被替換。在上面的例子中,從第一個到最后一個,隔一個被選擇的話,一共應該有 5 個值會被替換,那么在給它賦值的時候,必須給它賦 5 個值才能替換。其實在報錯的消息中已經告訴我們了,報錯是“值的錯誤”。
注意:s[i:j]=t和s[i:j:k]=t的操作是有差異的,后者要求迭代序列t的大小和s中被置換的元素個數要保持一致。
熟練掌握序列的基本操作,我們可以通過不同的手段和方式來達到同樣的目的。
2.3.4 可變序列及列表通用操作(二)
本小節繼續以列表為例介紹序列的通用操作(見表2-9)。
說明:復制序列copy()是一個非常重要的操作。
表2-9 可變序列及列表的通用操作(二)

將一個列表賦值給另一個列表不會產生新的列表對象。例如:

當我們把列表l賦給一個新的變量s后,改變s中元素的值,結果發現原列表l中的值也被改變了,說明s和l關聯的是同一個對象,這其實就是共享引用。

說明:全局函數id()也能檢測兩個對象是否是共享引用。
但這個結果可能并不是我們想要的。因為開始列表 l,是一個獨立的列表,以后要單獨對它進行操作。產生一個新的列表s,只不過要求列表s的值與l相同,但并不希望它們指向同一個對象。有兩種解決這個問題的方法:
方法一:利用切片操作取出列表的所有元素賦值給新的變量。

“s=l[:]”這種方式雖然使得s和l的值相同,但它們并沒有指向同一個對象。這就是前面講到的,l[:]和 l 看似結果相同(獲取所有元素的值),但實際上它們的作用是不一樣的。
對于“s=l[:]”這樣的操作方式,l和s 不屬于共享引用,當改變一個列表中某個元素的值時,另一個列表中相應位置的元素不會改變。
方法二:利用列表的方法“copy()”將列表的所有元素復制到新的變量中。


注意:關于這一點很容易出錯,請一定弄清楚。要正確理解第 2 章介紹的賦值邏輯,今后在介紹函數參數傳遞時經常會遇到這種情景。
以上介紹的這些操作屬于可變序列中的操作,由于列表是使用頻率最高的一個可變序列,所以,目前以列表為例進行講解,后面用到其他的可變序列時,這些通用操作也是支持的。接下來看有關列表所特有的一個操作。
列表中元素的順序與賦值時元素的順序是一致的,盡管可以通過“reverse()”方法進行反轉,但有時可能需要按照給定的條件進行排序,這時可以使用列表自帶的一個方法“sort()”來實現(見表2-10)。
表2-10 列表特有的操作

關于列表持有操作的幾點說明如下:
1)要求列表中的元素必須具有相同的類型

若一個列表含有數值、字符串等混合類型,則不能進行排序操作。
2)方法“sort()”和全局函數“sorted()”的區別

“sort()”方法沒有結果返回,只是改變原列表的排列順序。sorted()是全局函數,有結果返回,但原序列本身未改變。同時,全局函數不依附于任何的對象,因此,必須把序列以參數的形式傳遞給它。
3)方法“sort()”和全局函數sorted()的使用示例(學習了lambda函數后再來看下面的例子)

在調用每個函數的時候,盡量要做到心中有數,究竟是屬于整個序列的通用操作,還是屬于可變序列的通用操作,或者是某一個特定的類型所帶來的函數或方法,這樣才能靈活使用。
- Qt 5 and OpenCV 4 Computer Vision Projects
- C語言程序設計(第2 版)
- Mastering JavaScript Object-Oriented Programming
- PHP 從入門到項目實踐(超值版)
- JavaScript+jQuery網頁特效設計任務驅動教程(第2版)
- Programming ArcGIS 10.1 with Python Cookbook
- ASP.NET Core 2 and Vue.js
- Animate CC二維動畫設計與制作(微課版)
- C/C++常用算法手冊(第3版)
- Laravel Application Development Blueprints
- Qt 4開發實踐
- STM8實戰
- JavaEE架構與程序設計
- Web開發新體驗
- Splunk Essentials