python基礎之元組和列表

一、(列表、元組)知識點概念

1.1 序列(sequence)

Python中最基本的數據結構,序列中每個元素都有編號,即其位置或索引。包括列表和元組(類似於列表,只是不能修改)、字符串都屬於序列。因爲Python的內部原理,元組禁止修改。幾乎所有的元組都能用列表來代替,除了將元組用作字典鍵外。

1.2 容器(container)

容器基本上就是可包含其他對象的對象,Python中兩種主要的容器是序列(如列表和元組)和映射(如字典),在序列中每個元素都有編號,而在映射中每個元素都有名稱(也稱鍵)。有一種既不是序列也不是映射的容器,它就是集合(Set)。

二、(列表、元組)操作

有幾種操作適用於所有序列,包括索引、切片、相加、相乘和成員資格檢查。另外Python還提供了一些內置函數,可用於確定序列的長度以及找出序列中最大和最小的元素。還有一個重要的操作迭代(iteration)。

2.1 索引

序列中的所有元素都有編號——從0開始遞增,可使用編號來訪問各個元素。字符串、列表、元組都可通過索引獲取各個元素。

2.2 切片

1.默認步長
除使用索引來訪問單個元素外,還可以使用切片(slicing)來訪問特定範圍內的元素。爲此可使用兩個索引,並用冒號分隔。

In [1]: numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [2]:  numbers[0:1]
Out[2]: [1]

提供兩個索引來指定切片的邊界,其中第一個索引指定的元素包含在切片內,但第二個索引指定的元素不包含在切片內。
執行切片操作時,如果第一個索引指定的元素位於第二個索引指定的元素後(在這裏,倒數第3個元素位於第1個元素後面),結果就爲空序列。

In [3]: numbers[-3:0]
Out[3]: [] 

因此使用一種簡寫:如果切片結束於序列末尾,可省略第二個索引。

In [5]: numbers[-3:]
Out[5]: [8, 9, 10]

同樣,如果切片始於序列開頭,可省略第一個索引。

In [6]: numbers[:3]
Out[6]: [1, 2, 3]

要複製整個序列,可將兩個索引都省略。

In [7]: numbers[:]
Out[7]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

2.指定步長
執行切片操作時,你顯式或隱式地指定起點和終點,但通常省略另一個參數,即步長。在普通切片中,步長爲1。這意味着從一個元素移到下一個元素,因此切片包含起點和終點之間的所有元素。
如果指定的步長大於1,將跳過一些元素。例如,步長爲2時,將從起點和終點之間每隔一個元素提取一個元素。

In [8]:  numbers[0:9:2]
Out[8]: [1, 3, 5, 7, 9]

當然,步長不能爲0,否則無法向前移動,但可以爲負數,即從右向左提取元素。

In [9]: numbers[8:3:-1]
Out[9]: [9, 8, 7, 6, 5]

2.3 序列相加

可使用加法運算符來拼接序列。

In [10]: [1, 2, 3] + [4, 5, 6]
Out[10]: [1, 2, 3, 4, 5, 6]

In [11]: 'Hello,' + 'world!'
Out[11]: 'Hello,world!'

In [12]:  [1, 2, 3] + 'world!'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-67e1ff30f8a3> in <module>
----> 1 [1, 2, 3] + 'world!'
TypeError: can only concatenate list (not "str") to list

從錯誤消息可知,不能拼接列表和字符串,雖然它們都是序列。一般而言,不能拼接不同類型的序列。

2.4 乘法

將序列與數x相乘時,將重複這個序列x次來創建一個新序列:

In [13]: 'python' * 5
Out[13]: 'pythonpythonpythonpythonpython'

空列表是使用不包含任何內容的兩個方括號( [] )表示的。如果要創建一個可包含10個元素的列表,但沒有任何有用的內容,可使用 None 。在Python中, None 表示什麼都沒有。因此,要將列表的長度初始化爲10,可像下面這樣做:

In [14]: sequence = [None] * 10
In [15]: sequence
Out[15]: [None, None, None, None, None, None, None, None, None, None]

2.5 成員資格

要檢查特定的值是否包含在序列中,可使用運算符 in 。這個運算符與前面討論的運算符(如乘法或加法運算符)稍有不同。它檢查是否滿足指定的條件,並返回相應的值:滿足時返回 True ,不滿足時返回 False 。這樣的運算符稱爲布爾運算符,而前述真值稱爲布爾值。
在UNIX系統中,可在腳本中使用這兩行代碼來檢查對文件的寫入和執行權限。
接下來的示例檢查提供的用戶名mlh是否包含在用戶列表中,這在程序需要執行特定的安全策略時很有用(在這種情況下,可能還需檢查密碼)。
最後一個示例檢查字符串變量 subject 是否包含字符串 ‘$$$’ ,這用於垃圾郵件過濾器中。

In [14]: permissions = 'rw'
In [15]: 'w' in permissions
Out[15]: True
In [16]: 'x' in permissions
Out[16]: False
In [17]: users = ['mlh','foo','bar']
In [18]: input('請輸入用戶名:') in users
請輸入用戶名:mlh
Out[18]: True
In [19]: subject = '$$$ Get rich now!!! $$$'
In [20]: '$$$' in subject
Out[20]: True

三、列表

3.1 函數list

字符串不像列表可以對單個元素進行修改,因此在有些情況下可使用字符串來創建列表。

In [1]: lis = list('python')
In [2]: lis
Out[2]: ['p', 'y', 't', 'h', 'o', 'n']

In [3]: str = ''.join(lis)
In [4]: str
Out[4]: 'python'

3.2 基本的列表操作

可對列表進行所有的標準序列操作,如索引、切片拼接和相乘。也可以對列表進行修改:元素賦值、刪除元素、給切片賦值等。
1.修改列表:給元素賦值
使用索引表示法給特定位置的元素賦值,如lis[index] = newValue

In [5]: lis
Out[5]: ['p', 'y', 't', 'h', 'o', 'n']
In [6]: lis[2] = 'o'

In [7]: lis
Out[7]: ['p', 'y', 'o', 'h', 'o', 'n']

2.刪除元素
只需使用del語句即可從列表中刪除元素,del語句也可用於字典乃至變量。

In [8]: lis
Out[8]: ['p', 'y', 'o', 'h', 'o', 'n']
In [9]: del lis[2]
In [10]: lis
Out[10]: ['p', 'y', 'h', 'o', 'n']

3.給切片賦值
切片是一項及其強大的功能,而能夠給切片賦值則更加強大。

In [10]: lis
Out[10]: ['p', 'y', 'h', 'o', 'n']
In [11]: lis[1:] = list('pp')

In [12]: lis
Out[12]: ['p', 'p', 'p']

切片賦值還可以插入新元素。替換”了一個空切片,相當於插入了一個序列。

In [12]: lis
Out[12]: ['p', 'p', 'p']

In [13]: lis[1:1] = 'o'
In [14]: lis
Out[14]: ['p', 'o', 'p', 'p']

可採取相反的措施來刪除切片。

In [14]: lis
Out[14]: ['p', 'o', 'p', 'p']

In [15]: lis[1:] = ''
In [16]: lis
Out[16]: ['p']

3.3 列表方法

方法是與對象(序列-list、tuple、數、字符串、容器-set、字典-dict等)聯繫的函數。

1.append
方法 append 用於將一個對象附加到列表末尾。

In [17]: lis
Out[17]: ['p']

In [18]: lis.append(list('ython'))
In [19]: lis
Out[19]: ['p', ['y', 't', 'h', 'o', 'n']]

2.clear
方法 clear 就地清空列表的內容。

In [19]: lis
Out[19]: ['p', ['y', 't', 'h', 'o', 'n']]
In [20]: lis.clear()
In [22]: lis
Out[22]: []

3.Copy
方法 copy 複製列表。前面說過,常規復制只是將另一個名稱關聯到列表。類似於使用 a[:] 或 list(a) ,它們也都複製 a 。除了“=”是關聯另一個列表,其他copy方法都是完全new一個一樣的新對象。

In [28]: lis = list('python')
In [29]: id(lis)
Out[29]: 82077736
In [30]: lis1 = lis.copy()
In [31]: id(lis1)
Out[31]: 82188648
In [32]: lis2 = lis
In [33]: id(lis2)
Out[33]: 82077736
In [34]: lis3 = lis[:]
In [35]: id(lis3)
Out[35]: 77059936
In [36]: lis4 = list(lis)
In [37]: id(lis4)
Out[37]: 82171384
In [38]: lis4
Out[38]: ['p', 'y', 't', 'h', 'o', 'n']

4.count
方法 count 計算指定的元素在列表中出現了多少次。

In [39]: lis
Out[39]: ['p', 'y', 't', 'h', 'o', 'n']

In [40]: lis.count('p')
Out[40]: 1

5.extend
方法 extend 讓你能夠同時將多個值附加到列表末尾,爲此可將這些值組成的序列作爲參數提供給方法 extend 。換而言之,你可使用一個列表來擴展另一個列表。這可能看起來類似於拼接,但存在一個重要差別,那就是將修改被擴展的序列(這裏是 a )。在常規拼接中,情況是返回一個全新的序列。

In [41]: lis
Out[41]: ['p', 'y', 't', 'h', 'o', 'n']

In [42]: lis.extend(list('java'))
In [43]: lis
Out[43]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a']

另外,拼接操作並非就地執行的,即它不會修改原來的列表。要獲得與 extend 相同的效果,可將列表賦給切片,如下所示:

In [43]: lis
Out[43]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a']

In [44]: lis[len(lis):] = list('php')
In [45]: lis
Out[45]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

6.index
方法 index 在列表中查找指定值第一次出現的索引。如果引發了異常,則沒有找到這個單詞

In [45]: lis
Out[45]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

In [46]: lis.index('o')
Out[46]: 4

In [47]: lis.index('e')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-47-5d0d2f1b905f> in <module>
----> 1 lis.index('e')

ValueError: 'e' is not in list

7.insert
方法 insert 用於將一個對象插入列表。

In [49]: lis
Out[49]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

In [50]: lis.insert(2,list('go'))
In [51]: lis
Out[51]: ['p', 'y', ['g', 'o'], 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

與 extend 一樣,也可使用切片賦值來獲得與 insert 一樣的效果。有的時候會有差別。

In [55]: lis
Out[55]: ['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

In [56]: lis[2:2] = list('go')
In [57]: lis
Out[57]: ['p', 'y', 'g', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

8.pop
方法 pop 從列表中刪除一個元素(末尾爲最後一個元素),並返回這一元素。pop 是唯一既修改列表又返回一個非 None 值的列表方法。

In [61]: lis
Out[61]: ['p', 'y', 'g', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']
In [62]: lis.pop()
Out[62]: 'p'
In [63]: lis
Out[63]: ['p', 'y', 'g', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']

也可以指定從索引位置進行pop。

In [63]: lis
Out[63]: ['p', 'y', 'g', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']
In [64]: lis.pop(0)
Out[64]: 'p'
In [65]: lis
Out[65]: ['y', 'g', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']
In [66]: lis.pop(1)
Out[66]: 'g'
In [67]: lis
Out[67]: ['y', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']

使用 pop 可實現一種常見的數據結構——棧(stack)。棧就像一疊盤子,你可在上面添加盤子,還可從上面取走盤子。最後加入的盤子最先取走,這被爲後進先出(LIFO)。push 和 pop 是大家普遍接受的兩種棧操作(加入和取走)的名稱。Python沒有提供 push ,但可使用 append 來替代。方法 pop 和 append 的效果相反,因此將剛彈出的值壓入(或附加)後,得到的棧將與原來相同。

9.remove
方法 remove 用於刪除第一個爲指定值的元素。remove 是就地修改且不返回值的方法之一。不同於 pop 的是,它修改列表,但不返回任何值。

In [69]: lis
Out[69]: ['y', 'o', ['g', 'o'], 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']

In [70]: lis.remove(list('go'))
In [71]: lis
Out[71]: ['y', 'o', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h']

10.reverse
方法 reverse 按相反的順序排列列表中的元素,就地進行翻轉。

In [2]: lis
Out[2]: ['p', 'y', 't', 'h', 'o', 'n']
In [3]: lis.reverse()
In [4]: lis
Out[4]: ['n', 'o', 'h', 't', 'y', 'p']

注意到 reverse 修改列表,但不返回任何值(與 remove 和 sort 等方法一樣)。

11.sort
方法 sort 用於對列表就地排序。就地排序意味着對原來的列表進行修改,使其元素按順序排列,而不是返回排序後的列表的副本。

In [5]: lis
Out[5]: ['n', 'o', 'h', 't', 'y', 'p']

In [6]: lis.sort()
In [7]: lis
Out[7]: ['h', 'n', 'o', 'p', 't', 'y']

前面介紹了多個修改列表而不返回任何值的方法,在大多數情況下,這種行爲都相當自然(例如,對 append 來說就如此)。需要強調 sort 的行爲也是這樣的,因爲這種行爲給很多人都帶來了困惑。在需要排序後的列表副本並保留原始列表不變時,通常會遭遇這種困惑。排序是就地進行修改列表的,因此若想保留排序前的列表,可以先將列表copy一份,再進行排序。另一種方法是使用sorted()。

In [10]: lis
Out[10]: ['p', 'y', 't', 'h', 'o', 'n']

In [11]: sorted(lis)
Out[11]: ['h', 'n', 'o', 'p', 't', 'y']

In [12]: lis
Out[12]: ['p', 'y', 't', 'h', 'o', 'n']

12.高級排序
方法 sort 接受兩個可選參數: key 和 reverse 。這兩個參數通常是按名稱指定的,稱爲關鍵字參數,將在第6章詳細討論。參數 key 類似於參數 cmp :你將其設置爲一個用於排序的函數。然而,不會直接使用這個函數來判斷一個元素是否比另一個元素小,而是使用它來爲每個元素創建一個鍵,再根據這些鍵對元素進行排序。因此,要根據長度對元素進行排序,可將參數 key 設置爲函數 len 。

In [15]: x
Out[15]: ['aardvark', 'abalone', 'acme', 'add', 'aerate']

In [16]: x.sort(key=len)
In [17]: x
Out[17]: ['add', 'acme', 'aerate', 'abalone', 'aardvark']

對於另一個關鍵字參數 reverse ,只需將其指定爲一個真值( True 或 False)以指出是否要按相反的順序對列表進行排序。

In [21]: x.sort(key=len,reverse=True)
In [22]: x
Out[22]: ['aardvark', 'abalone', 'aerate', 'acme', 'add']

四、元組

與列表一樣,元組也是序列,唯一的差別在於元組是不能修改的(你可能注意到了,字符串也不能修改)。元組語法很簡單,只要將一些值用逗號分隔,就能自動創建一個元組。

In [2]: 'python','java','php'
Out[2]: ('python', 'java', 'php')

用圓括號括起(常用的做法):

In [3]: ('python','java','php')
Out[3]: ('python', 'java', 'php')

空元組用兩個括號就行:

In [4]: ()
Out[4]: ()

如何表示只包含一個值的元組呢?這有點特殊:雖然只有一個值,也必須在它
後面加上逗號。

In [6]: 'python',
Out[6]: ('python',)
In [5]: ('python',)
Out[5]: ('python',)

(‘python’) 與 ‘python’ 完全等效。但僅僅加上一個逗號,就能完全改變表達式的值。函數 tuple 的工作原理與 list 很像:它將一個序列作爲參數,並將其轉換爲元組 。如果參數已經是元組,就原封不動地返回它。

In [7]: tuple([('python', 'java', 'php')])
Out[7]: (('python', 'java', 'php'),)

In [8]: tuple(['python', 'java', 'php'])
Out[8]: ('python', 'java', 'php')

In [9]: tuple('python')
Out[9]: ('p', 'y', 't', 'h', 'o', 'n')

In [10]: tuple(('python','java'))
Out[10]: ('python', 'java')

五、小結

序列:序列是一種數據結構,其中的元素帶編號(編號從0開始)。列表、字符串和元組都屬於序列,其中列表是可變的(你可修改其內容),而元組和字符串是不可變的(一旦創建,內容就是固定的)。要訪問序列的一部分,可使用切片操作:提供兩個指定切片起始和結束位置的索引。要修改列表,可給其元素賦值,也可使用賦值語句給切片賦值。

成員資格:要確定特定的值是否包含在序列(或其他容器)中,可使用運算符 in 。將運算符 in 用於字符串時情況比較特殊——這樣可查找子串。
In [21]: users = (‘mlh’,‘foo’,‘bar’)
In [22]: ‘mlh’ in users
Out[22]: True

方法:一些內置類型(如列表和字符串,但不包括元組)提供了很多有用的方法。方法有點像函數,只是與特定的值相關聯。方法是面向對象編程的一個重要方面。

函 數 描 述
len(seq) 返回序列的長度
list(seq 將序列轉換爲列表
max(args) 返回序列或一組參數中的最大值
min(args) 返回序列和一組參數中的最小值
reversed(seq) 讓你能夠反向迭代序列
sorted(seq) 返回一個有序列表,其中包含指定序列中的所有元素
tuple(seq) 將序列轉換爲元組
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章