列表和元組
?
1、python的數據結構
1.1、序列類型
python中內置的序列類型:
-
列表(list)
-
元組(tuple)
-
字符串(str)
-
隊列(deque)
-
字節(bytes)
-
數組(arrray)
-
內存視圖(memoryview)
等等
序列類型都共有的操作:迭代、切片、排序、拼接、索引取值、相加、相乘、成員檢查等等
1.2、其他類型
- 字典(dict)(又叫映射)
- 數字類型:
- 整形(int)
- 浮點數(float)
- 復數(complex)
- 布爾值(bool)
- 集合(set)
2、列表和元組
2.1、簡介
列表和元組都是python內置的容器序列類型。
容器序列和扁平序列:
- 容器序列存放的是它們所包含的任意類型的對象的引用,可存放任意類型的數據
- 扁平里存放的是值而不是引用。即扁平序列其實是一段連續的內存空間,是它里面只能存放諸如字 符、字節和數值這種基礎類型。
元組和列表區別在與:元組是不可變的(不可修改),列表是可變的。
在編寫代碼的過程中,如果我們希望要使用的數據不能被修改,可以使用元組去存儲。另外由于元組不可變,并且元組可hash,所以元組可作為字典的鍵使用(具體介紹見字典一文)。
2.2、序列的通用操作
序列類型通用的操作:迭代、切片、排序、拼接、索引取值、相加、相乘、成員檢查等等
2.2.1、索引
序列中的元素從左往右,索引從0開始依次遞增。從右往左則是從-1開始依次遞減。
>>> a = [1,2,3,4,5]
>>> a[0]
1
>>> a[4]
5
>>> a[-1]
5
>>> a[-5]
1
索引也能從字面量直接取值
>>> 'abcdefg'[2]
'c'
>>> (1,2,3,4,5)[2]
3
弱索引超出序列范圍,會拋出IndexError異常
>>> (1,2,3,4,5)[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
2.2.2、切片
索引能訪問序列單個元素,切片則是訪問序列特定范圍的元素。
>>> a
[1, 2, 3, 4, 5]
>>> a[1:3]
[2, 3]
>>> a[1:-2]
[2, 3]
如上,切片需傳入兩個索引,用以確認切片的范圍。注意:切片取值不會包含區間范圍的最后一個元素,這樣 做帶來的好處如下。
-
當只有最后一個位置信息時,我們可以快速看出切片里有幾個元素:list_a[:2] 返回 2個元素的列表。
-
當起止位置都可見時,我們可以快速計算出切片的長度,用后一個索引減去起始位置索引(stop - start)即可。list_a[3:5],長度為2。
-
這樣做也讓我們可以利用任意一個下標來把序列分割成不重疊的兩部分,如list_a[:x] 和 list_a[x:] ,以X分隔。
2.2.2.1、切片簡寫
>>> list_a = list('abcdefg') #序列類型轉換。可將可迭代類型數據轉換成一個列表
>>> list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a[:] #當不輸入索引時,會復值整個序列
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a[:-3] #當從序列開始位置取值時,可省略第一個索引
['a', 'b', 'c', 'd']
>>> list_a[2:] #當切片取值到序列尾部,可省略第二個索引
['c', 'd', 'e', 'f', 'g']
>>> list_a[5:-3] #當第一個索引在第二個索引后面時,取值一定為空
[]

當當第一個索引在第二個索引后面時

2.2.2.2、切片的步長
切片有三個參數可選
[start, stop[, step]]
開始索引,結束索引,步長(默認為1)
前面我門取值時,使用的默認步長1,即索引+1,挨個取值。步長可根據需求指定,如下
>>> list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a[::2] #步長為而,即索引+2取值。
['a', 'c', 'e', 'g'] #索引0,2,4,6位置的值
索引可以為負傷,即倒著取值。 注意:-0 仍然為 0
>>> list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a[1:5:-1] #索引取值方向以正數相反,所以此處為空(將上圖箭頭反過來)
[]
>>> list_a[5:1:-1] #順序為5,4,3,2
['f', 'e', 'd', 'c']
步長負數提取看著挺別捏的,好在不常用。經常使用步長為負的情況是將序列倒序
>>> list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a[::-1]
['g', 'f', 'e', 'd', 'c', 'b', 'a']
2.2.3、相加
序列可以使用+進行拼接
>>> list_a + list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list_a + 'aaaa' #不同類型的序列一般不能相加
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
>>> list_a += [1,2,3] #可變序列的增量運算會將原序列更改
>>> list_a
['a', 'b', 'c', 'd', 'e', 'f', 'g', 1, 2, 3]
2.2.4、相乘
將序列乘以num時,將重復這個序列num次來創建一個新序列
>>> list_a*3
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> 'abc'*2
'abcabc'
>>> id(a[0])
2391575279872
>>> id(a[2])
2391575279872
注意:序列乘以小于0的數,會被當作0來相乘。不能乘
>>> ['a']*-1
[]
>>> ['a']*0
[]
>>> ['a']*0.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
>>> 'a'*-1
''
注意:當使用*創建一個包含多個空列表的列表時需注意以下情況
>>> a = [[]]*10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(2)
>>> a
[[2], [2], [2], [2], [2], [2], [2], [2], [2], [2]]
這里是創建了一個包含10個空列表的列表,但是由于列表里的是另一列表的引用,所以*10后,這10個空列表都指向同一列表。可參考如下方式創建:
>>> [list() for i in range(10)] #列表推導式,循環初始化10個列表
[[], [], [], [], [], [], [], [], [], []]
>>> a = [list() for i in range(10)]
>>> a[0].append(2)
>>> a
[[2], [], [], [], [], [], [], [], [], []]
或者使用None代替空列表
2.2.5、成員檢查
序列的成員檢查使用in進行,如下:
>>> 'a' in 'abc'
True
>>> 'a' in 'bc'
False
>>> [1,2] in [[1,2], [3,3]]
True
成員檢查即檢查特定的值是否包含在指定的序列內。是這返回True,否則返回False。
像這樣返回True/False的運算符加布爾運算符。
True/False是布爾值(bool)
2.2.6、長度、最大值、最小值
如下,即計算序列的長度、最大值、最小值并返回
>>> len([1,2,3])
3
>>> max([1,2,3])
3
>>> min([1,2,3])
1
2.2.7、元素索引和出現次數
序列可使用s.index(x[, i[, j]])方法,找出x 在 s 中首次出現項的索引號(索引號在 i 或其后且在 j 之前)
>>> 'abc'.index('c')
2
>>> 'abcddcdc'.index('c',3,7)
5
s.count(x)計算 x 在 s 中出現的總次數
>>> 'abdksaghdikjasbc'.count('a')
3
2.2.8、比較
相同類型的序列也支持比較。
特別地,tuple 和 list 的比較是通過比較對應元素的字典順序。 這意味著想要比較結果相等,則每個元素比較結果都必須相等,并且兩個序列長度必須相同。
2.3、列表
https://docs.python.org/zh-cn/3/tutorial/datastructures.html#more-on-lists
2.3.1、可變序列操作
bytearray僅接受滿足 0 <= x <= 255 值限制的整數)。
| 運算 | 結果: | 備注 |
|---|---|---|
s[i] = x |
將 s 的第 i 項替換為 x | |
s[i:j] = t |
將 s 從 i 到 j 的切片替換為可迭代對象 t 的內容 | |
del s[i:j] |
等同于 s[i:j] = [] |
|
s[i:j:k] = t |
將 s[i:j:k] 的元素替換為 t 的元素 |
(1) |
del s[i:j:k] |
從列表中移除 s[i:j:k] 的元素 |
|
s.append(x) |
將 x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x]) |
|
s.clear() |
從 s 中移除所有項 (等同于 del s[:]) |
(5) |
s.copy() |
創建 s 的淺拷貝 (等同于 s[:]) |
(5) |
s.extend(t) 或 s += t |
用 t 的內容擴展 s (基本上等同于 s[len(s):len(s)] = t) |
|
s *= n |
使用 s 的內容重復 n 次來對其進行更新 | (6) |
s.insert(i, x) |
在由 i 給出的索引位置將 x 插入 s (等同于 s[i:i] = [x]) |
|
s.pop() 或 s.pop(i) |
提取在 i 位置上的項,并將其從 s 中移除 | (2) |
s.remove(x) |
從 s 中移除第一個 s[i] 等于 x 的條目 |
(3) |
s.reverse() |
就地將列表中的元素逆序。 | (4) |
注釋:
-
如果 k 不等于
1,則 t 必須與它所替換的切片具有相同的長度。 -
可選參數 i 默認為
-1,因此在默認情況下會移除并返回最后一項。 -
當在 s 中找不到 x 時
remove()操作會引發ValueError。 -
當反轉大尺寸序列時
reverse()方法會原地修改該序列以保證空間經濟性。 為提醒用戶此操作是通過間接影響進行的,它并不會返回反轉后的序列。 -
包括
clear()和copy()是為了與不支持切片操作的可變容器 (例如dict和set) 的接口保持一致。copy()不是collections.abc.MutableSequenceABC 的一部分,但大多數具體的可變序列類都提供了它。Added in version 3.3:
clear()和copy()方法。 -
n 值為一個整數,或是一個實現了
__index__()的對象。 n 值為零或負數將清空序列。 序列中的項不會被拷貝;它們會被多次引用,正如 通用序列操作 中有關s * n的說明。
2.3.2、列表對象的所有方法
-
list.append(x)在列表末尾添加一個元素,相當于
a[len(a):] = [x]。 -
list.extend(iterable)用可迭代對象的元素擴展列表。相當于
a[len(a):] = iterable。 -
list.insert(i, x)在指定位置插入元素。第一個參數是插入元素位置的索引,因此,
a.insert(0, x)在列表開頭插入元素,a.insert(len(a), x)等同于a.append(x)。 -
list.remove(x)從列表中刪除第一個值為 x 的元素。未找到指定元素時,觸發
ValueError異常。 -
list.pop(i)移除列表中給定位置上的條目,并返回該條目。 如果未指定索引,則
a.pop()將移除并返回列表中的最后一個條目。 如果列表為空或索引在列表索引范圍之外則會引發IndexError。 -
list.clear()刪除列表里的所有元素,相當于
del a[:]。 -
list.index(x[, start[, end]])返回列表中第一個值為 x 的元素的零基索引。未找到指定元素時,觸發
ValueError異常。可選參數 start 和 end 是切片符號,用于將搜索限制為列表的特定子序列。返回的索引是相對于整個序列的開始計算的,而不是 start 參數。 -
list.count(x)返回列表中元素 x 出現的次數。
-
list.sort(*, key=None, reverse=False)就地排序列表中的元素(要了解自定義排序參數,詳見
sorted())。并非所有數據都可以排序或比較。排序依賴于比較,所以需要序列內元素都能相互比較才能進行排序。
-
list.reverse()翻轉列表中的元素。
-
list.copy()返回列表的淺拷貝。相當于
a[:]。
多數列表方法示例:
>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4) # 從 4 號位開始查找下一個 banana
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'
2.3.3、列表推導式
列表推導式使創建列表的方式更簡潔。常見的用法為,對序列或可迭代對象中的每個元素應用某種操作,用生成的結果創建新的列表;或用滿足特定條件的元素創建子序列。
例如,創建平方值的列表:
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
等價于:
squares = [x**2 for x in range(10)]
這種寫法更簡潔、易讀。
列表推導式的方括號內包含以下內容:一個表達式,后面為一個 for 子句,然后,是零個或多個 for 或 if 子句。結果是由表達式依據 for 和 if 子句求值計算而得出一個新列表
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
等價于:
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
嵌套
matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
>>>[[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
等價于:
>>> transposed = []
>>> for i in range(4):
... # 以下 3 行實現了嵌套的列表組
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
2.4、元組
元組是不可變的序列類型,他擁有普通序列的通用操作,除此之外沒有用其他新的方法。
>>> tuple([1,2,3])
(1, 2, 3)
>>> (1,2,3)
(1, 2, 3)
>>> t = 12345, 54321, 'hello!'
>>> t
(12345, 54321, 'hello!')
>>> t[0]
12345
# 元組可以嵌套:
>>> u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
# 元組是不可變對象:
>>> t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # 但它們可以包含可變對象:
>>> v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
構造 0 個或 1 個元素的元組比較特殊:為了適應這種情況,對句法有一些額外的改變。用一對空圓括號就可以創建空元組;只有一個元素的元組可以通過在這個元素后添加逗號來構建(圓括號里只有一個值的話不夠明確)。
>>> empty = ()
>>> len(empty)
0
>>> singleton = 'hello', # <-- 注意末尾的逗號
>>> len(singleton)
1
>>> singleton
('hello',)
浙公網安備 33010602011771號