列是指有序的隊列,重點在"有序"。
Python中的序列主要以下幾種類型:
按照序列是否可被改變分類:
這裡說的通用序列操作是指大部分可變序列與不可變序列都支持的操作。一般操作包括 增、刪、改、查,但是這裡說的是包括不可變序列也支持的通用操作,因此只能是“查”操作。
符號說明:
序列通用操作及結果說明:
說明:
a) 對於序列來說,其元素的數字類型是不做嚴格區分的,如True=1=1.0,False=0=0.0;
b) 相同類型的序列也支持比較操作,特別是tuple和list是通過比較對應元素的字典順序來進行比較的。這意味著要判斷兩個序列相等,就需要這兩個序列中的每個元素都相等,並且這兩個序列必須是相同類型且長度相等。
注意:
a) 雖然in 和 not in操作只用於一般情況下的簡單容器測試,但一些專用序列(如str,bytes和bytearray)也用於子序列測試。
>>> "ll" in "hello"
True
b) 如果s * n中n小於0,則n會被當做0看待;s * 0的結果是產生一個與s相同類型的空序列。
>>> "ss" * -2
''
>>> ["Tom", "Peter", "Jerry"] * -2
[]
>>> ("Tom", "Peter", "Jerry") * -2
()
c) 對於s * n操作,s序列中的元素沒有被復制,他們只是被引用了多次。
>>> lists = [['a']] * 3
>>> lists
[['a'], ['a'], ['a']]
>>> lists[0].append('b')
>>> lists
[['a', 'b'], ['a', 'b'], ['a', 'b']]
d) 對於序列的切片操作s[i:j[:k]],如果i或j負數,則索引是相對於字符串的尾部來計算的。如果i是負數,則i相當於len(s)+i,如果j是負責,則j相當於len(s)+j。
>>> [0,1,2,3,4,5,6,7,8,9][-1]
9
>>> [0,1,2,3,4,5,6,7,8,9][-5:-1]
[5, 6, 7, 8]
>>> [0,1,2,3,4,5,6,7,8,9][1:-1]
[1, 2, 3, 4, 5, 6, 7, 8]
e) 還是對於序列的切片操作s[i:j[:k]],其中i與j的值有如下幾種情況:
>>> s = (0,1,2,3,4,5,6,7,8,9)
>>> len(s)
10
>>> s[6:12]
(6, 7, 8, 9)
>>> s[:5]
(0, 1, 2, 3, 4)
>>> s[5:]
(5, 6, 7, 8, 9)
>>> s[9:5]
()
如果步長k被指定,則切片結果中的元素為i,i+k,i+2k,i+3k,...到j的前一個元素停止。k的值不能為0,如果k為None則其值取1。
>>> s[1::2]
(1, 3, 5, 7, 9)
>>> s[0::2]
(0, 2, 4, 6, 8)
>>> s[0::0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: slice step cannot be zero
f) 連接不可變序列時總是會導致產生一個新的對象。這意味著通過重復連接構建序列將會在在總序列長度中具有二次運行時成本。要獲得線性運行成本,必須切換到以下選項之一:
g) 一些序列類型(例如 range)僅支持遵循特定模式的元素序列,因此不支持序列的連接和重復操作。
h) 對於s.index(x[, i[, j]])操作,當在序列s中找不到x元素時,index會拋出ValueError。另外,附加參數i,j允許對該序列的子序列進行有效的查找,這大致相當於s[i,j].index(x),但是不會拷貝任何數據且返回的索引值是相對於序列的開始位置而不是相對於切片的開始位置。
這裡來說下可變序列類型支持,而不可變序列類型不支持的操作。在序列通用操作中主要說明的是“查”操作,這裡要說的是可變序列的 "增"、“刪”、“改”操作。
符號說明:
可變序列支持的操作及結果說明:
注意:
a) 可變序列的clear()和copy()方法實在Python 3.3中新加的方法,是為了與dict、set這些不支持切片操作的容器所提供的接口保持一致性。
b) 對於 s = n操作,如果n小於0或等於0,序列s將被清空;另外如果n大於1,序列s並沒有被復制,它們只是被引用了多次,這與序列通用操作中的s n是一樣的。
不可變序列類型通常實現而可變序列沒有實現的唯一操作是對內建hash()方法的支持。對內建hash()的支持允許不可變序列(例如tuple)用作dict的鍵並存儲在set和frozenset的實例中。如果嘗試hash一個包含不可被hash的數據的不可變序列會導致TypeError錯誤。
Python中的基本序列類型包括: list、tuple、range,而str屬於特殊序列類型,專門用於處理文本序列,這個後面單獨進行說明。
Python中的列表是可變序列,通常用於存儲相同類型的數據集合,當然也可以存儲不同類型數據。Python中的列表表現形式有點像其他語言中的屬組:列表中的元素是用方括號[]括起來,以逗號進行分割。
class list([iterable]) # 這裡的方括號表示iterable是可選項
列表構造函數list(iterable)會創建一個與可迭代對象iterable中的條目及條目順序都相同的列表。可迭代對象iterable可以是一個序列(sequence)、一個支持迭代操作的容器(container),也可以是一個迭代器對象(iterator object)。如果iterable已經是一個list,則創建一個copy並返回,類似於iterable[:]。如果沒有指定參數,列表構造函數會創建一個新的空list, []。
>>> list1 = [] # 空列表
>>> list1
[]
>>> list2 = ["Tom", "Jerry", "Lucy", "Peter"] # 非空列表
>>> list2
['Tom', 'Jerry', 'Lucy', 'Peter']
>>>
>>> list3 = list() # 列表構造函數創建空列表
>>> list3
[]
>>> list4 = list(list2)
>>> list4
['Tom', 'Jerry', 'Lucy', 'Peter']
>>>
>>> list5 = [x for x in list2] # 列表生成式
>>> list5
['Tom', 'Jerry', 'Lucy', 'Peter']
list實現了所有通用(common)序列操作和可變序列(mutable sequence)操作,此外,list還提供了一些附加方法。
>>> s = [1, 2, 3, 'a', 'b', 'c']
>>> 1 in s # 包含判斷
True
>>> 1.0 in s # 數字不嚴格區分類型(1==1.0==True)
True
>>> 1 not in s # 不包含判斷
False
>>> s + ['d', 'e', 'f'] # 拼接操作
[1, 2, 3, 'a', 'b', 'c', 'd', 'e', 'f']
>>> s * 2 # 重復2次
[1, 2, 3, 'a', 'b', 'c', 1, 2, 3, 'a', 'b', 'c']
>>> s[3] # 獲取下標為3的條目
'a'
>>> s[3:6] # 獲取序列s的切片,下標分別為 3,4,5
['a', 'b', 'c']
>>> s[1:6:2] # 獲取序列s的切片,步長為2,下標分別為 1,3,5
[2, 'a', 'c']
>>> len(s) # 獲取序列長度
6
>>> min(s) # min()和max()的參數中,數據類型需要有可比性
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() < int()
>>> max([1, 2, 3, 4.0, 5.0])
5.0
>>> min([1, 2, 3, 4.0, 5.0, False])
False
>>>
>>> [1, 2, 3, 4, 2, 5, 6, 3, 2].index(2) # 獲取2在序列s中第一次出現的下標位置
1
>>> [1, 2, 3, 4, 2, 5, 6, 3, 2].index(2, 3) # 獲取序列s從下標3開始查找2第一次出現的下標位置
4
>>> s.count(2) # 統計2在序列s中出現的次數
1
>>> [1, 2, 3, 4, 2, 5, 6, 3, 2].count(2)
3
>>> len([1, 2, 3, 4, 5]) # 獲取序列長度
5
>>> s = [1, 2, 3, 4]
>>> s
[1, 2, 3, 4]
>>> s.append(5) # 向list末尾追加一個條目
>>> s
[1, 2, 3, 4, 5]
>>> s.insert(0,0) # 向list開始位置插入一個條目
>>> s
[0, 1, 2, 3, 4, 5]
>>> s.extend([6, 7, 8, 9]) # 擴展list, 向list末尾拼接多個條目
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s[9] = 99 # 將list中下標為9的條目替換為99
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 99]
>>> s[6:9] = ['a', 'b'] # 將list中范圍為從6到9(不包含9)的切片替換為['a', 'b']
>>> s
[0, 1, 2, 3, 4, 5, 'a', 'b', 99]
>>> s[6:10]=['A','B'] # 同上,此處10為list的長度,表示切片范圍是到list末尾的
>>> s
[0, 1, 2, 3, 4, 5, 'A', 'B']
>>> s.pop() # 移除list末尾的條目
'B'
>>> s
[0, 1, 2, 3, 4, 5, 'A']
>>> s.pop(5) # 移除list中下標為5的條目
5
>>> s
[0, 1, 2, 3, 4, 'A']
>>> s.remove('A') # 移除list中的指定條目'A'
>>> s
[0, 1, 2, 3, 4]
>>> del s[1:5:2] # 刪除list中下標為 1,3 的條目
>>> s
[0, 2, 4]
>>> s.reverse() # 將list中元素位置進行反轉,list本身發生改變
>>> s
[4, 2, 0]
>>> s.copy() # list淺拷貝,list本身不發生改變
[4, 2, 0]
>>> s
[4, 2, 0]
>>> s *= 2 # 相當於 s = s * 2
>>> s
[4, 2, 0, 4, 2, 0]
sort(*, key=None, reverse=None)
此方法僅s使用 < 符號進行列表項目之間的比較,即默認對列表進行升序排序。排序過程中的異常不會被捕獲,也就是說如果任何比較操作失敗,整個排序操作將失敗,並且列表可能保留部分已修改狀態。
sort()只能通過關鍵字(僅限關鍵字參數)傳遞的兩個參數如下:
說明:
sort()方法會直接修改list,這在對大列表進行排序時可以節約空間;該方法的副作用是不會返回排序後的list,可以使用sorted()顯示請求一個新的排序後的list實例;
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
sort()方法保證穩定性。如果能保證兩個比較相當的元素不會改變相對位置,那麼這個排序就是穩定的,這有助於通過多個條件進行排序,比如 先按部門排序,然後再按工資級別排序。
CPython實現細節:當一個列表正在被排序時,如果嘗試修改或檢測列表,效果是列表為定義。Python的C實現使得列表在持續時間內顯示為空,並且如果它檢測到列表在排序期間已發生改變,則會拋出ValueError錯誤。
>>> s = ['A', 'b', 'C', 'd', 'e']
>>> s.sort()
>>> s
['A', 'C', 'b', 'd', 'e']
>>> s.sort(key=str.lower)
>>> s
['A', 'b', 'C', 'd', 'e']
>>> s.sort(key=str.upper)
>>> s
['A', 'b', 'C', 'd', 'e']
>>> s.sort(key=str.upper, reverse=True)
>>> s
['e', 'd', 'C', 'b', 'A']
>>> s.sort(reverse=True)
>>> s
['e', 'd', 'b', 'C', 'A']
>>> sorted(s) # sorted()可以對任何可迭代對象驚醒排序,不會對原數據進行修改且會返回一個排序後的實例
['A', 'C', 'b', 'd', 'e']
>>> s
['e', 'd', 'b', 'C', 'A']
>>>
Tuple是不可變序列,通常用於存儲異構數據集合,例如由內置函數enumerate()產生的2元組。元祖還用於同構數據的不可變序列的情況,例如允許在set或dict實例中存儲。
class tuple([iterable]) # 此處的方括號表示iterable是可選參數
tuple構造函數tuple(iterable)會創建一個與可迭代對象iterable中的條目及條目順序都相同的元祖。可迭代對象iterable可以是一個序列(sequence)、一個支持迭代操作的容器(container),也可以是一個迭代器對象(iterator object)。如果iterable已經是一個tuple,則直接返回這個tuple。如果沒有指定參數,元組構造函數會創建一個新的空tuple, ()。
說明:
實際上,是逗號產生了一個元祖,而不是小括號。除了空元組的情形或者需要避免語法模糊的時候外,小括號是可選的。例如f(a, b, c)是具有3個參數的函數調用,而f((a, b, c))是以3元祖作為唯一參數的函數調用。
>>> 1, # 有逗號結尾表示元組
(1,)
>>> (1, )
(1,)
>>> 1 # 沒逗號結尾表示數字
1
>>> (1)
1
>>> () # 空數組
()
>>> tuple()
()
>>> tuple([1, 2, 4]) # 非空數組
(1, 2, 4)
>>> 1, 2, 3
(1, 2, 3)
>>> (1, 2, 3)
(1, 2, 3)
tuple是不可變序列,它支持所有通用序列操作(與list一致,此處不再給出示例),但不支持可變序列操作。
range類型表示一個不可變的數字序列,通常用於在for循環中循環特定次數。
class range(stop)
class range(start, stop[, step])
start:表述數字序列開始值,如果該參數沒有被提供則值為0
stop: 數字序列結束值
stop: 數字序列步長,如果該參數沒有被提供則值為1
關於start、stop、step參數值的說明:
>>> list(range(10)) # start沒有指定,默認值為0,即start=0,end=10
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1,11)) # start=1, end=11
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(range(0, 11, 2)) # 要指定step就必須要指定start
[0, 2, 4, 6, 8, 10]
>>> list(range(0, -10, -1)) # step為負數
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
>>> list(range(0))
[]
>>> list(range(10, 5)) # 如果end < start ,則range對象為空
[]
這裡需要注意一下,Python 2.x中的range()函數返回的是一個list類型,而Python 3.x中的range()函數返回的是一個range類型。
Python 2.x
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
Python 3.x
>>> range(10)
range(0, 10)
range實現了除連接(concatenation)和重復(repetition)之外的所有通用序列操作,這是由於range對象只能表示遵循嚴格模式的序列,而連接和重復操作通常會違反這個模式。
range相對於常規list和tuple的優點在於:無論它表示的范圍的大小是多少,它始終占用相同(小)量的內存。這是因為它只需要存儲 start、end和step這3個值,然後根據需要計算各個條目和子范圍。
說明:
測試range對象是否相等與序列一樣通過 == 和 != 進行比較,也就是說,如果兩個range對象表示相同值的序列就被認為是相等的。需要注意的是,比較相等的兩個range對象可能具有不同的start、end、step參數值,例如 (0) == (2, 1),又例如 (0, 3, 2) == (0, 4, 2)