文章目錄
- 5.1.1 列表用作棧
- 5.1.2 列表用作隊列
- 5.1.3 列表的理解
- 5.1.4 嵌套列表的理解
這章將更加詳細的描述你已經學過的東西,並添加一些新的內容。
5.1 更多有關列表
列表資料類型有更多的方法,下面是列表對象的所有方法:
list.append(x),在列表的末尾添加一項,等同於a[len(a):] = [x]。
list.extend(L),通過追加給定列表的所有項來擴充列表,等同於a[len(a):] = L。
list.insert(i, x),在指定的位置插入一項。第一個參數是將要在它前面進行插入的元素的索引,所以a.insert(0, x)在列表的最前端插入,並且a.insert(len(a), x)等同於a.append(x)。
list.remove(x),移除列表裡面第一個值為x的項。如果列表裡面沒有這個項將報錯。
list.pop([i]),移除列表裡面指定位置的項,並返回它。如果沒有指定索引,a.pop()移除並返回列表裡面的最後一項。(在方法簽名裡面i用方括弧包圍表示參數是可選的,並不是你應該在那個位置輸入方括弧。)
list.index(x),返回列表裡面第一個值為x的項的索引。如果列表裡面沒有這個項將報錯。
list.count(x),返回列表裡面x出現的次數。
list.sort(),按位置排序列表裡面的所有項。
list.reverse(),按位置反轉列表裡面的所有項。
一個樣本使用了列表的大多數方法:
你或許已經注意到了像insert,remove或sort這些修改列表的方法並沒有傳回值被列印出來,它們返回None。對於Python裡面所有的可修改的資料結構這是一個設計原則。
5.1.1 列表用作棧
列表的方法可以比較容易的把列表作棧來使用,最後一個元素添加的地方正是第一個元素獲得的地方(後進先出)。在棧的頂端添加一項,使用append()方法。在棧的頂端獲得一項,使用pop()方法並且不用指定參數。例如:
5.1.2 列表用作隊列
也可以把列表當作一個隊列來使用,第一個元素添加的地方正是第一個元素獲得的地方(先進先出);對於這個目的列表不是很有效。從列表的末尾追加和彈出非常快,在列表的開頭進行插入和彈出是很慢的(因為所有其它的元素都需要移動一個位置)。
實現一個隊列,使用collections.deque,它被設計為從兩端追加和彈出都非常快。例如:
5.1.3 列表的理解
列表理解提供一個簡潔的方式來建立列表。普通的應用將建立一個新列表,它的每一個元素都是一些操作應用於另一個序列或可迭代對象的每一個成員的結果,或者建立一個那些元素的滿足一個確定條件的子序列。
例如,假定我們想建立一個平方的列表,像:
我們可以獲得同樣的結果:
這同樣也等同於squares = list(map(lambda x: x**2, range(10))),但是更加簡潔和可讀。
一個列表的理解是由一個包含後跟for從句的運算式,然後是零個或多個for或if從句的方括弧組成的。結果是一個新的列表,源於在這個運算式後面的for或if從句的上下文中來計算這個運算式。例如,這個listcomp將串連兩個列表的元素如果它們不相等的話:
它等同於:
注意for和if語句的順序在這些程式碼片段中是如何一樣的。
如果運算式是一個元組(例如上一個樣本中的(x, y)),它必須被括住:
列表的理解可以包含複雜的運算式和嵌套的函數:
5.1.4 嵌套列表的理解
一個列表理解裡面的初始設定式可以是任意運算式,包含另一個列表的理解。
考慮下面這個3x4矩陣的樣本實現為一個元素為3個長度為4的列表的列表:
下面的列表理解將轉置所有的行和列:
就像我們在上一節中所看到的,嵌套的listcomp在它後面的for語句的上下文中被計算,所以這個樣本等同於:
按順序,和下面的一樣:
在現實世界中,你應該優先選擇內建函數而不是複雜的語句流。對於這種用法zip()函數將做一大部分工作:
5.2 del語句
有一種方式使用元素的索引而不是元素的值從列表裡面移除一項:del語句。這和帶有傳回值的pop()方法不同。del語句也可以用於從列表裡面移除切片或清空整個列表(稍早前我們的做法是給一個切片賦一個空列表)。例如:
del也可以用於刪除整個變數:
在這以後再引用名稱a將報錯(至少直到另一個值賦給它)。我們稍後將發現del的其它用法。
5.3 元組和序列
我們看到列表和字串有許多共同的屬性,像索引和切片操作。它們是序列資料類型的兩個例子。因為Python是一個正在進化的語言,其它序列資料類型也可以被加進來。也有另一個標準的序列資料類型:元組。
一個元組由一些逗號分割的值組成,例如:
就像你看到的那樣,在輸出元組的時候總是用圓括弧括住,所以嵌套的元組也可以被正確解釋;在輸入的時候可以有或沒有圓括弧包圍,雖然通常不管怎樣圓括弧是必須的(如果元組是一個大的運算式的一部分)。不可能對一個元組的單個項進行賦值,然而可以建立一個包含可變對象的元組,就像列表。
雖然元組看起來像列表,它們通常用於不同的情況和不同的目的。元組是不可改變的,通常包含一個複雜序列的元素通過解壓縮或索引來進行訪問。列表時可改變的,它的元素通常是同類的並且通過在列表上進行迭代來訪問。
一個特別的問題是包含零個或一個項的元組的建立:要適應它的話文法有一些極其奇怪。空的元組由一對空的圓括弧組成;有一個項的元組由後面帶逗號的值組成(用圓括弧括住一個單一的值是不夠的)。看上去很醜,但很有效。例如:
語句t = 12345, 54321, 'hello!'是一個元組壓縮的例子;值12345,54321和'hello!'被一起壓縮到一個元組裡。相反的操作也是可以的:
這被叫做序列解壓縮是足夠合適的並對右邊的序列起作用。序列解壓縮要求等號左邊的變數數目和右邊的序列元素數目相等。注意多元賦值就是元組壓縮和序列解壓縮的結合。
5.4 集合
Python也包含集合資料類型。集合是一個無序,不重複的資料集。基本的應用程式套件括成員關係測試和去除重複實體。集合對象同樣支援數學運算,像並集,交集,差集和對稱差集。
花括弧或set()函數可以用來建立集合。注意,建立一個空的集合必須使用set(),而不是{}。後者是用來建立空字典的,我們在下一節討論這個資料結構。
這是一個簡單的示範:
和列表的理解相似,集合的理解也支援:
5.5 字典
另一個Python內建的有用的資料類型是字典。字典在其它語言裡通常叫做關聯儲存或關聯陣列。不像序列,它是通過一系列數字來索引的。字典是通過索引值來索引的,可以是任何不可變的類型。字串和數字都可以作為鍵。元組也可以用作鍵如果它只包含字串,數字或元組。如果一個元組直接或間接的包含了可變對象,它不可以再作為鍵。你不可以使用列表作為鍵,因為列表可以使用索引按位置賦值,切片賦值,或像append()和extend()方法。
最好把字典認為成一個無序的索引值對集合。要求是在一個字典裡面的所有鍵都必須是唯一的。一對花括弧建立一個空的字典。放入一個逗號分割的索引值對列表就是初始化了這個字典,這就是字典輸出的方式。
字典的主要操作就是使用鍵來儲存或擷取值。也可以使用del運算式來刪除索引值對。如果你使用了一個已經存在的鍵進行儲存時,那麼這個鍵所關聯的舊值將會被覆蓋。如果使用一個不存在的鍵來擷取值的話會產生一個錯誤。
在一個字典上執行list(d.keys())返回一個所有鍵的列表,任意順序(如果你希望排序的話,使用sorted(d.keys()))。檢查一個鍵是否在字典裡,使用in關鍵字。
這是一個使用字典的小例子:
dict()建構函式直接從序列的索引值對構建字典:
另外,字典的理解可以從任何的索引值運算式建立字典:
當鍵是簡單的字串時,使用關鍵字參數來指定索引值對有時候更加容易:
5.6 迴圈技術
當迴圈字典時,鍵和對應的值可以使用items()方法同時或得到:
當迴圈序列時,位置索引和對應的值可以使用enumerate()函數同時獲得:
同時迴圈兩個或更多的序列時,可以使用zip()函數進行項的配對:
當以逆序迴圈一個序列時,首先指定序列為向前的方向,然後調用reversed()函數:
當以一定的順序迴圈一個序列時,使用sorted()函數,它返回一個新的已排序的列表,而不修改原來的:
想要在迴圈裡面改變你正在迭代的序列(例如重複某個確定的項),強烈建議你先做一個拷貝。迴圈一個序列並不隱式的做一個拷貝。切片的記法使這個變得尤其方便:
5.7 更多有關條件
while和if運算式的條件可以包含任何操作符,不僅僅是比較。
比較操作符in和not in檢查一個值是否在序列裡面。操作符is和is not比較兩個對象是否是同一個對象,這隻是對於可變對象,如列表的事情。所有的比較操作符有相同的優先順序,低於所有的數字操作符。
比較可以被連結在一起。例如a < b == c測試a是否小於b,此外b是否等於c。
比較可以使用布爾操作符and和or結合起來,比較的結果(或任何其它的布林運算式)可以使用not取反。這些操作符的優先順序低於比較操作符,在它們之間,not有最高的優先順序,or最低,所以A and not B or C 和(A and (not B)) or C相等。括弧總是可以用來表達期望的組合。
布爾操作符and和or就是被叫做的所謂的短路操作符,它們的參數是從左至右計算。當結果可以確定時,計算立馬就會停止。例如,如果A和C是true,但是B是false,A and B and C將不計算運算式C。當用於一般的值而不是布爾值,短路操作符的傳回值是最後一個計算的參數。
可以把比較和其它布林運算式的值賦給變數。例如:
注意,在Python裡不像C那樣,賦值不能出現在運算式裡面。C程式員可能會抱怨,它為了避免在C程式裡遇到的一個普通類別的問題,當你需要相等符號==時卻輸入了賦值符號=。
5.8 序列和其它類型的比較
同樣類型的序列可以比較。比較使用詞典裡的順序。首先使用第一對元素進行比較,如果不同的話就可以決定比較的結果了。如果相同,就比較第二對元素,等等,直到任何一個序列的元素使用完。如果被比較的兩個元素它們本身又是相同類型的序列,按字典順序比較被遞迴的進行。如果所有的元素都相等,序列就被認為是相等的。如果一個序列是另一個序列起始位置的子序列,短的序列是較小的那個。詞典順序對於字串來說使用Unicode編碼點數字來排序單個字元。一些相同類型的序列比較樣本:
注意,使用<和>比較不同類型的對象是合法的,只要對象能夠提供合適的比較方法。例如,混合數字類型通過它們的數字值來比較,索引0等於0.0。否則,而不是提供一個任意的排序,解譯器將產生一個類型錯誤異常。
本文是對官方網站內容的翻譯,原文地址:http://docs.python.org/3/tutorial/datastructures.html