本文將詳細介紹 Python 的六大數據結構,包括數值、字符串、列表、元組、集合、字典等。閱讀本文預計需要 15 min。
一文了解Python數據結構
1. 前言
數據結構對編程中非常重要的一部分,掌握 Python 數據結構非常必要。本文主要總結 Python 六大數據結構:
- 數值
- 字符串
- 列表
- 元組
- 集合
- 字典
2. 數值
Python 中有 3 種數值類型,分別是整型(int)、浮點型(float)、複數型(complex)。此外布爾型(bool)是整型的子類。通過下面的例子來直觀感受一下:
# 多個變量賦值
a, b, c, d = 10, 6.66, 10+5j, False
print(f"a的類型爲:{type(a)}") # type(x) 可以查看 x 的類型
print(f"b的類型爲:{type(b)}")
print(f"c的類型爲:{type(c)}")
print(f"d的類型爲:{type(d)}")
輸出結果:
a的類型爲:<class 'int'>
b的類型爲:<class 'float'>
c的類型爲:<class 'complex'>
d的類型爲:<class 'bool'>
3. 字符串
文本信息是一種非常重要的信息。在 Python 中,字符串來充當這種角色。在 Python 中字符串是不可變對象,不可以被修改,要修改只能通過重新開闢內存空間,創建新的對象來實現。
這裏需要說明一下,Python 中變量更像一個標籤,這個標籤指向存儲了數據的地址,我們可以通過 id()
函數來查看對象的內存地址。
s = 'a'
print(f's 變量的值是:{s},s 變量的地址是:{id(s)}')
s += 'b' # 等價於 s = s + 'b'
print(f's 變量的值是:{s},s 變量的地址是:{id(s)}')
結果輸出:
s 變量的值是:a,s 變量的地址是:2014533253552
s 變量的值是:ab,s 變量的地址是:2014533384432
通過上面這個例子我們可以看到,字符串不可以被改變,一旦改變,內存地址就會發生變化。相當於重新賦值。
3.1 創建字符串
創建字符串有以下幾種方式:單引號、雙引號、三引號、str()函數。代碼直觀演示如下:
s1 = 'a' # 單引號創建單行字符串
s2 = "b" # 創建單行字符串
s3 = '''
這是三個單引號創建的
多行字符串!'''
s4 = """
這是三個雙引號創建的
多行字符串!"""
s5 = str([1, 2, 3]) # [1, 2, 3] 是列表,後面會講,這裏是把列表轉化爲字符串
print(f'單引號創建的單行字符串內容是:{s1}')
print(f'雙引號創建的單行字符串內容是:{s2}')
print(f'三個單引號創建的多行字符串內容是:{s3}')
print(f'三個雙引號創建的多行字符串內容是:{s4}')
print(f'str() 函數創建的字符串內容是:{s5}')
輸出結果:
單引號創建的單行字符串內容是:a
雙引號創建的單行字符串內容是:b
三個單引號創建的多行字符串內容是:
這是三個單引號創建的
多行字符串!
三個雙引號創建的多行字符串內容是:
這是三個雙引號創建的
多行字符串!
str() 函數創建的字符串內容是:[1, 2, 3]
3.2 下標和切片
下標在 Python 中是一個編號,字符串、列表、元組都可以用下標來索引,我們可以通過下標來找到其對應的元素
。注意:下標是從 0 開始編號的,用0-(n-1)索引
。假如我們有一個字符串 s = 'abcd'
,現在我想得到這個字符串的第 1 個元素,那麼我們可以通過 s[0]
得到第 1 個元素。此外 Python 還支持負數索引,用(-n)-(-1)
來索引。s[-1]
表示倒數第 1 個元素。測試如下:
In [1]: s = 'abcd'
In [2]: s[0]
Out[2]: 'a'
In [3]: s[-1]
Out[3]: 'd'
切片是指對操作的對象截取其中一部分的操作。字符串、列表、元組都支持切片操作。切片操作是一個淺拷貝操作,它只拷貝第一層對象。關於深拷貝和淺拷貝,留作以後探討。切片的語法規則是:[開始:結束:步長]
,注意以下幾點:
- 開始、結束、步長省略時,開始默認從頭開始,結束默認到結尾,步長默認爲 1。
- 結束取不到,如:
s = '0123'
,s[0:3]
截取的是s[0], s[1], s[2]
,截取不到s[3]
,即取前不取後。 - 切片支持負數索引。
測試如下:
In [1]: s = '0123456789'
In [2]: s[0:3]
Out[2]: '012'
In [3]: s[-3:-1]
Out[3]: '78'
In [4]: s[0:10:2]
Out[4]: '02468'
3.3 字符串的常用操作
我們可以對字符串進行很多操作,比如首字母大寫、查找、替換、拼接等等。在 Python 中內置了很多字符串操作的方法,我們可以通過 dir(str)
查看字符串的內置方法,在通過 help(str.function)
查看該方法的用法。或者直接打開下載的 Python 官方文檔檢索查看 str
對象的方法。
這裏主要列幾個用的比較多的方法。
str.split(sep=None, maxsplit=-1)
方法常用來把字符串轉化爲列表(list),它將字符串 str
以 sep
爲分隔符,以 maxsplit
爲分割次數,轉化爲列表。測試如下:
In [18]: s = 'Python is a great language!'
In [19]: s.split(' ')
Out[19]: ['Python', 'is', 'a', 'great', 'language!']
In [20]: s.split(' ', 1)
Out[20]: ['Python', 'is a great language!']
In [21]: s.split()
Out[21]: ['Python', 'is', 'a', 'great', 'language!']
str.join(iterable)
方法常用來把列表(list)轉化爲字符串,是一種常用高效的字符串拼接方法,它的含義是用 str
去拼接iterable
中的每個元素。這裏需要注意:iterable 的每個元素必須都是字符串類型,否則會報 TypeError
。測試如下:
my_list = ['Python', 'is', 'great!']
result = ' '.join(my_list) # 用空格連接 my_list 中的各個元素
print(result)
輸出結果:
Python is great!
如果將 my_list
更改爲 my_list = ['Python', 'is', 'great!', 3]
,那麼程序會報錯,TypeError: sequence item 3: expected str instance, int found
。因爲 3
是 int
類型。
此外還可以通過 +
實現字符串拼接功能。在字符串中,我們可以用 +
和 *
來增加字符串。其中 +
是拼接字符串,*
是重複字符串。測試如下:
name_info = '我的名字是Jock,'
age_info = '年齡是25歲!'
my_info = name_info + age_info # 這裏加號把兩個字符串拼接在一起
print(f'name_info + age_info 結果是:{my_info}')
s = 'abc'
s *= 3 # 等價於 s = s * 3,即把 'abc' 重複 3 次
print(s)
輸出結果:
name_info + age_info 結果是:我的名字是Jock,年齡是25歲!
abcabcabc
str.replace(old, new[, count])
方法是實現將字符串 str
中所有的old
字符片段替換爲 new
片段,如果給出了 count
參數,則只替換 count
次。測試如下:
In [11]: s = 'abcdabcdabcd'
In [12]: s.replace('a', 'f', 1)
Out[12]: 'fbcdabcdabcd'
In [13]: s.replace('a', 'f')
Out[13]: 'fbcdfbcdfbcd'
str.strip([chars])
方法常用來處理字符串的邊界,比如去除字符串兩端的空格等,它將字符串 str 兩側 [chars]
列表中出現的字符都去除,如果省略 [chars] 則默認去除字符串 str 兩側的空格。測試如下:
In [22]: ' Python '.strip()
Out[22]: 'Python'
In [23]: 'www.example.com'.strip('cmowz.')
Out[23]: 'example
4. 列表
列表(list)是 Python 中非常重要且常用的數據類型。在 Python 中 list 是一個可變序列。這裏的可變是指 list 的元素個數可以增加或減少。列表用 []
包圍,每個元素用 ,
分隔。
list 非常強大,我們可以把 list 當做一個大容器,什麼都可以往裏面裝,比如:字符串、字典、列表、元組等。此外列表也支持下標和切片操作,非常靈活強大。
4.1 創建列表
我們可以通過以下幾種方式創建一個列表。
list_a = []
,創建一個空列表,推薦使用。list_b = list()
,使用 list() 函數創建一個空列表。list_c = [x for x in range(10)]
,使用列表推導式創建一個列表。
4.2 增加列表元素
往列表中增加元素主要有以下幾種方法:
list.append(x)
:將元素 x 添加到 list 尾部,等價於list[len(list):len(list)] = [x])
list.extend(list_b)
:將 list_b 中所有的元素添加到 list 中,等價於list += list_b
list.insert(i, x)
:在 list 下標爲 i 的位置插入 x,等價於list[i:i] = [x]
+
:列表也可以直接拼接 list_a += list_b
測試如下:
list_a = [1, 2]
list_a.append(3)
print(f'list_a = [1, 2],list_a.append(3) 是:{list_a}')
list_b, list_c = [1, 2, 3], [4, 5, 6]
list_b.extend(list_c)
print(f'list_b = [1, 2, 3],list_c = [4, 5, 6], list_b.extend(list_c) 是:{list_b}')
list_d = [1, 2, 3]
list_d.insert(0, 5)
print(f'list_d = [1, 2, 3],list_d.insert(0, 5) 是:{list_d}')
list_e, list_f = [1, 2, 3], [4, 5, 6]
print(f'list_e = [1, 2, 3],list_f = [4, 5, 6], list_e + list_f 是:{list_e + list_f}'')
結果如下:
list_a = [1, 2],list_a.append(3) 是:[1, 2, 3]
list_b = [1, 2, 3],list_c = [4, 5, 6], list_b.extend(list_c) 是:[1, 2, 3, 4, 5, 6]
list_d = [1, 2, 3],list_d.insert(0, 5)是:[5, 1, 2, 3]
list_e = [1, 2, 3],list_f = [4, 5, 6], list_e + list_f 是:[1, 2, 3, 4, 5, 6]
這裏提一下,append()、extend()、insert() 方法都是在原有的 list 上添加,不會開闢新的內存空間,而用 +
會開闢新的內存空間,增加開銷。應該根據具體需求靈活進行選擇。
4.3 刪除列表元素
刪除列表元素主要有以下方法:
- del list[index]:根據下標進行刪除,刪除 list 下標爲 index 的元素。
- pop list[index]:根據下標進行刪除,刪除並返回 list 下標爲 index 的元素。
- list.remove(x):根據值進行刪除,刪除 list 中 x 元素,一次只刪除一個 x。
- del list[:]:刪除 list 中的所有元素,list 變爲空列表。
- list.clear():刪除 list 中的所有元素,list 變爲空列表。
- del list: 刪除整個列表對象。
4.4 修改列表元素值
修改列表元素值的主要是通過下標來確定要修改的是哪個元素,然後才能修改。格式: list[index] = value
將 list[index] 的值修改爲 value。測試如下:
In [37]: list_a = [1, 2, 3]
In [38]: list_a[0] = 4
In [39]: list_a
Out[39]: [4, 2, 3]
4.5 查詢列表元素
查詢列表元素的值有以下幾種方法:
- list[index]:返回列表中下標是 index 的元素。
- in:判斷某個元素是否在列表中,如果在,返回 True,否則返回 False。
- not in:判斷某個元素是否在列表中,如果不在,返回 True,否則返回 False
- list.index(x):返回列表中元素 x 的下標。
- list.count(x);返回列表中元素 x 出現的次數。
4.6 列表的排序
列表可以通過下標索引,它是一個有序序列,所以我們可以對列表進行排序。排序的方法有以下兩種:
- list.sort(*, key=None, reverse=False):穩定的原地排序。默認將 list 由小到大排序,reverse=True 可改爲倒序,由大到小。
- sorted(list):對於原 list 沒有改變,返回一個排好序的列表,默認是升序,reverse=True 可改爲倒序,由大到小。
- list.reverse():將 list 翻轉。
4.7 列表作爲棧和隊列使用
在 Python 中所有可變數據結構都遵循一個設計原則:原地修改可變對象是沒有返回值的,或者說返回值是 None。比如 list 中的 sort、insert、remove 方法等。
列表可以作爲棧(stack)使用,可以快速的實現(LIFO)後進先出,通過 pop() 和 append() 方法即可。用法如下:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
同時列表也可以做隊列(queue)使用,實現(FIFO)先進先出,通過 pop(0) 和 append() 方法實現。但是由於列表在末尾添加和刪除一個元素是非常快的,但是在開頭添加和刪除一個元素速度比較慢,因爲在列表的擡頭添加或刪除一個元素,都需要移動後面的所有元素。
這時候我們可以使用 collections.deque,它可以實現在開頭和結尾都快速的刪除和添加一個元素。用法如下:
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
5. 元組
元組(tuple)是 Python 中一種不可變的序列。因爲元組是不變的序列
,所以我們不可以對元組進行修改。元組用 ()
包圍,每個元素用 ,
分隔,只有一個元素時,也要有一個 ,
。
爲什麼有了列表,還要設計一個不可變的元組呢?因爲可變,雖然靈活,但是存在風險,所以元組不可變,代碼相對更加安全。
元組可以認爲是一種特殊的列表,除了會改變自身的方法不通用之外,其他的通用。比如列表中的 append()、extend()、insert()等方法不能用於元組。
創建一個元組我們有以下幾個方法:
- t = ():創建一個空元組,推薦。
- t = tuple():創建一個空元組。
- t = (1, ):創建只有一個元素的元組,注意這裏一定要有逗號。
元組其實也是可以”改變“的。元組中的元素是不可以改變的,但是如果元組中的元素是可變對象,比如 list 的話,那麼這時候這個可變對象是可以改變的。看下面的例子:
In [56]: t = (1, 2, 3)
In [57]: t[0] = 5
這裏會報錯:
TypeError: 'tuple' object does not support item assignment
In [58]: t = (1, [0, 1], 3)
In [59]: t[1][0] = 6
In [60]: t
Out[60]: (1, [6, 1], 3)
通過上面的例子我們可以發現,其實元組也是可以“改變”的,我們可以這樣理解,上面這個例子中,t = (1, [0, 1], 3)
,元組 t 中的第二個元素其實是指向了列表[0, 1]的地址,列表[0, 1] 的地址沒有改變,但是該地址的內存空間存儲的值可以改變。
6. 集合
Python 中集合(set)是一個無序、可哈希的集合。集合具有確定性、互異性、無序性。創建集合的意義:
- 利用集合來去重。假如我們要對 list_a 進行去重,那麼可以這麼操作。list_a = list(set(list_a)).
- 判斷一個數是否在集合。x in s 或者 x not in s。因爲集合是可哈希的,所以它的查找時間複雜度爲 O(1),效率遠高於列表。
- 此外我們還可以用集合來求交集、並集、補集等運算。
我們可以通過 s = set()
創建一個空集合,注意:s = {}
創建的是一個空字典。
更多 set 的用法可以用查看官方文檔。
7. 字典
字典(dictionary)是 Python 中另一種極爲重要的數據類型,是 Python 中唯一一個映射容器,用途非常廣泛。字典也是可變的。字典是用{}
包圍的,專門存儲 key: value
,即鍵值對的容器,各鍵值對用逗號分隔。
它不同於列表和元組等序列通過下標來索引,字典是通過鍵(key)來索引的。
字典中鍵必須是不可變的:
- 通常我們用
數字
和字符串
來作爲字典的鍵。 - 元組也可以作爲字典的鍵,前提是元組中不包含可變對象,比如 (1, 2, 3) 可以作爲鍵,但是 ([1, 2], 2) 不可以作爲字典的鍵。
- 列表不可以作爲字典的鍵。因爲列表是可變的。
7.1 創建字典
創建字典可以通過以下方式創建:
- d = {}:創建一個空字典。
- d = dict():利用 dict()函數創建一個空字典。
測試如下:
In [62]: a = dict(one=1, two=2, three=3)
In [63]: b = {'one': 1, 'two': 2, 'three': 3}
In [64]: c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
In [65]: d = dict([('two', 2), ('one', 1), ('three', 3)])
In [66]: e = dict({'three': 3, 'one': 1, 'two': 2})
In [67]: a == b == c == d == e
Out[67]: True
7.2 增加字典元素
往字典中添加元素,我們有以下幾種方法:
d[key] = value
:用這個操作來往字典中添加元素存在風險,可能會使得我有的 key-value 被更改,所以用這個方法前要用 key in d 進行鍵的判斷。- d.update([other]):other 可以是另一個字典,也可以是其他可迭代的鍵值對。也存在覆蓋已有的 key-value 的風險。
- d.setdefault(key[, default]):當存在 key 時獲取它對應的值,如果不存在這個 key,就加入這個 key,並把它對應的值設爲 default ,並返回 default。default 默認是 None
7.3 刪除字典元素
刪除字典元素有以下幾種方法:
- del d[key]:刪除字典元素 d[key]。
- d.clear():清空字典,變爲空字典。
- del d:刪除字典。
- d.pop(key[, default]):如果 d 中存在 key 那麼刪除 key-value 鍵值對,並返回 key 對應的 value。如果 key 不存在,則返回 default,未指定 default 則報錯 KeyError 。
- d.popitem():刪除並返回一個鍵值對元組,即:(key, value)。注意:從 Python3.7 開始,刪除的鍵值對遵循後進先出原則(LIFO)。在版本 Python 3.7 之前是任意刪除返回一個鍵值對。
7.4 修改字典元素
我們可以通過 d[key] = value
來修改字典元素,如果 key 不存在,則會往字典中添加 key-value 鍵值對。
7.5 查詢字典元素
查詢字典中的元素我們有以下幾種方法:
- key in d:查詢 key 是否在 字典 d 中,如果在返回 True ,否則返回 False.
- key not in d:查詢 key 是否在 字典 d 中,如果不在返回 True ,否則返回 False.
- d[key]:返回 key 對應的 value。如果 key 不存在,報錯 KeyError
- d.get(key[, default]):這是 d[key] 的友好模式。如果 key 在字典中,返回其對應的 value,否則返回 default,default 默認爲 None。
7.6 字典的遍歷
- 遍歷字典的 key:for key in d
- 遍歷字典的 value: for value in d.values()
- 遍歷字典的項:for item in d.items()
- 遍歷字典的 key-value: for key, value in d.items()
示例如下:
d = {"one": 1, "two": 2, "three": 3, "four": 4}
print('遍歷字典的key')
for key in d:
print(key)
print('遍歷字典的value')
for value in d.values():
print(value)
print('遍歷字典的item')
for item in d.items():
print(item)
print('遍歷字典的key-value')
for key, value in d.items():
print(key, value)
結果輸出:
遍歷字典的key
one
two
three
four
遍歷字典的value
1
2
3
4
遍歷字典的item
('one', 1)
('two', 2)
('three', 3)
('four', 4)
遍歷字典的key-value
one 1
two 2
three 3
four 4
for 循環的用法,我們下次學習會總結。這部分中字符串、列表、字典非常重要,它們的方法也很多,很難全部記住。如果忘記了我們及時查看官方文檔的用法即可,不一定非要死記硬背。
8. 小結
學習這部分之後我們需要:
- 掌握可變對象和不可變對象區別。
- 掌握字符串、列表、元組、字典、集合的增刪改查操作。
- 瞭解下標和切片。
- 瞭解每一種數據結構的應用場景。
9. 巨人的肩膀
推薦閱讀: