目錄
2.5 列表(list)
2.5.1 索引和切片
列表的索引和切片,用法和字符串的索引和切片一模一樣,區別在於,面臨二維或多維列表時,會有多重索引和切片,思路就是「一層一層往里剝」。
L = [1, 2, 3, 4, [9, 8, 7, 6]]
len(L)
L[4]
L[4][1]
L[4][::-1]
2.5.2 常用方法
2.5.2.1 添加元素
方法 | 含義 | 原地操作? |
---|---|---|
append(x) | 將元素x添加至列表尾部 | 是 |
extend(L) | 將列表L中所有元素添加至列表尾部 | 是 |
insert(index, x) | 在列表指定位置index處添加元素x,該位置后面元素后移一位 | 新生成 |
+ | 添加元素至列表尾部 | 新生成 |
* | 拼接字符串 | 新生成 |
alist = [1, 2, 3]
blist = [4, 5, 6]
alist.extend(blist) # blist添加至alist后面,原地操作
alist
alist.append(blist)
alist
# append和+的區別
import time
result = []
start = time.time() # 返回當前時間
for i in range(10000): # 創建一個整數列表
result = result + [i]
print('+添加:', time.time()-start) # 打印列表長度,並計算耗時
result = []
start = time.time()
for i in range(10000):
result.append(i)
print('Append:', time.time()-start)
# append和insert區別
import time
a = []
start = time.time()
for i in range(100000):
a.insert(0, i)
print('Insert:', time.time()-start) # 新生成
a = []
start = time.time()
for i in range(100000):
a.append(i)
print('Append:', time.time()-start) # 原地操作
L = [1, 2, 3, 4, 5, 6]
L*3 # 通過乘實現復制
2.5.2.2 刪除元素
方法 | 含義 | 原地操作? |
---|---|---|
remove(x) | 刪除首次出現的指定元素x | 是 |
pop(index) | 刪除指定index元素,並返回該元素的值,index默認-1 | 是 |
clear(index) | 刪除列表中所有元素,保留列表對象 | 是 |
del | 刪除列表中元素或整個列表 | / |
賦值 | 對列表中元素或整個列表進行賦值,也算一種刪除 | 是 |
拓展:刪除列表重復元素有兩種思路:
- for循環中的i基於內容去遍歷,用i in list[:]
- for循環中的i基於index去遍歷,用i in range(len(list)-1, -1, -1)
L = [1, 2, 3, 4, 4, 5, 6]
L.remove(4) # 原地操作
L
# 刪除重復元素法1
x = [3, 4, 5, 5, 6]
for i in x[:]: # 采用切片的方式
print(i)
if i == 5:
x.remove(i)
print(x)
# 刪除重復元素法2
x = [3, 4, 5, 5, 6]
for i in range(len(x)-1, -1, -1): # 從后向前的順序
print(i)
if x[i] == 5:
del x[i]
print(x)
L = [2, 3, 4, 5]
L.pop(2) # 實現兩個功能:取出4,把4從原列表刪除
L = [2, 3, 4, 5]
L.clear()
L
L = [1, 2, 3, 4, 5]
id(L)
L[0:2] = [6, 6] # 修改多個元素
L
id(L)
L = [1, 2, 3, 4, 5]
del L[1] # 刪除第一個
L
del L # 刪除整個列表
L
2.5.2.3 計算&排序
方法 | 含義 | 原地操作? |
---|---|---|
index(x) | 返回列表中第一個值為x元素的下標,若不存在則拋出異常 | / |
count(x) | 返回指定元素x在列表中出現的次數 | / |
reverse() | 對列表所有元素進行逆序 | 是 |
sort(key=,reverse=) | 對列表元素進行排序,key指定排序依據,reverse決定升序降序:True降序、False升序 | 是 |
需要注意,reverse
方法和sort
方法,都有對應的排序函數:
函數 | 含義 | 原地操作? |
---|---|---|
reversed(L) | 對列表L所有元素進行逆序,返回是一個迭代器,需要list化顯示 | 是 |
sorted(list, key=, reverse=) | 對列表元素進行排序,key指定排序依據,reverse決定升序降序:True降序、False升序 | 新生成 |
且無論是在sort
還是sorted
排序中,參數key通常采用匿名函數「lambda」。
x = [3, 4, 5, 6]
x.index(5) # 返回索引,不存在則報錯
x.count(10) # 沒有返回0,不會報錯
x.reverse() # 原地逆序
x
x = [2, 3, 1, 5, 8]
x.sort() # 默認是升序
x
x.sort(reverse=True) # 降序
x
# 自定義排序,使用匿名函數
aList = [[3, 4], [15], [11, 9, 17, 13], [6, 7, 5]]
aList.sort(key=lambda x: len(x), reverse=True) # 按長度排序,lambda函數,匿名函數
aList
x = [1, 2, 3, 4, 5]
list(reversed(x)) # 新生成
student = [['john', 'A', 15], ['jane', 'B', 12], ['dave', 'B', 10]] # 按值進行排序
sorted(student, key=lambda a: a[2], reverse=True)
2.5.2.4 類型轉換
字符串和列表經常互相轉換,具體方法是list
和join
:
- 函數
list(str)
:把字符串轉化為列表 - 方法
' '.join(L)
:把列表轉化為字符串
s = 'abcd'
list(s)
x = ['apple', 'peach', 'banana', 'peach', 'pear']
'/'.join(x)
2.5.2.5 復制
常見的復制有三種:賦值、淺拷貝、深拷貝,三者在使用和表現上都存在區別。
2.5.2.5.1 賦值
賦值操作是復制了引用指針,所以數據一方改變,必然導致另一方變化,原理見下圖:

# 實質是復制了引用:一方改變,必然導致另一方變化
L1 = [1, 2, 3, 4]
id(L1)
L2 = L1
L2[0] = 0
L2
id(L2)
L1
2.5.2.5.2 淺拷貝
淺拷貝有4種形式,而不同維度的數據,在淺拷貝后數據的變化也不盡相同,需要分開討論,原理見下圖及代碼:
copy()
方法- 使用列表生成式
- 用for循環遍歷
- 切片


# 一維:原來值和淺拷貝值互不影響
L1 = [1, 2, 3, 4]
L2 = L1[:]
L2[0] = 0
L2
L1
# 二維或多維:分兩種情況討論
x = [1, 2, 3, [4, 5, 6]]
y = x[:]
y[0] = 0 # 復雜子對象不改變:原來值和淺拷貝值互不影響
y
x
x = [1, 2, 3, [4, 5, 6]]
y = x[:]
y[3][2] = 10 # 復雜子對象改變:原來值和淺拷貝值互相影響
y
x
2.5.2.5.3 深拷貝
- 深拷貝是完全的拷貝,原來值和深拷貝值互不影響
- 使用
copy
模塊中的deepcopy()
方法生成
import copy
L1 = [1, 2, 3, [4, 5]]
L2 = copy.deepcopy(L1)
L2[0] = 0
L2
L1 # 原來值和深拷貝值互不影響
2.5.3 內置函數
函數 | 含義 | 是否新生成 |
---|---|---|
len() | 返回列表中的元素個數 | / |
max()、min() | 返回列表中的最大、最小元素 | / |
sum() | 對列表元素進行求和運算 | / |
zip() | 將多個列表對應位置的元素組合成元組,返回可迭代的zip對象 | 是 |
enumerate() | 枚舉列表元素,返回元組迭代器,元組中元素包含列表下標、元素的值 | 是 |
L = [1, 2, 3, 4, 5, 6]
sum(L)
L1 = ['a', 'b', 'c']
L2 = [1, 2, 3]
list(zip(L1, L2)) # 生成的是元組迭代器
# 把下標和值打印出來
L1 = ['a', 'b', 'c']
for i, j in enumerate(L1):
print(i, j)
2.5.4 列表推導式
- 閱讀:先看第一個for,再看第二個for,再看條件判斷(if),最后看輸出結果(表達式)
- 格式:
- [表達式 for 變量 in 列表]
- [表達式 for 變量 in 列表 if 條件]
- 作用:
- 實現嵌套列表的平鋪
- 過濾不符合條件的元素
- 使用多個循環實現多序列元素的任意組合
- 實現矩陣轉置
- 使用函數或復雜表達式
- 實現向量的運算
# 用for循環實現
L1 = [1, 2, 3, 4, 5]
L3 = []
for i in L1:
L3.append(i**2)
L3
L1 = [1, 2, 3, 4, 5]
[i**2 for i in L1] # 列表推導式
squar1 = map(lambda x: x**2, L1) # 用map函數實現對L1的指定映射
list(squar1)
# 列表推導式,加上判斷條件
L1 = [1, 2, 3, 4, 5]
[i**2 for i in L1 if i > 2]
[[i, j] for i in range(10) for j in range(10) if i == j]
L1 = [1, 2, 3, 4]
L2 = [4, 5, 6, 7]
[L1[i]+L2[i] for i in range(len(L1))]
L1 = [1, 2, 3, 4]
L2 = [4, 5, 6, 7]
[L1[i]+L2[j] for i in range(len(L1)) for j in range(len(L2)) if i == j]
2.6 字典(dictionary)
2.6.1 創建
字典有三種創建方式:
- 直接賦值創建
- 用
dict()
函數創建 - 通過給定鍵值對創建
# 直接賦值創建
addresbook1 = {"小明": "1521055", "小華": "1872345", "小芳": "1389909"}
addresbook1
# 用dict()函數創建
alist = [1, 2, 3]
blist = ['a', 'b', 'c']
dict(zip(alist, blist)) # 將多個列表對應位置的元素組合成元組,返回可迭代的zip對象
# 通過給定鍵值對創建
dict(name='小明', age=20) # 等號前是鍵,等號后是值
2.6.2 讀取
讀取原理:通過key
訪問value
。
方法 | 含義 |
---|---|
[key] | 以鍵作為下標讀取元素,若不存在則拋出異常 |
get(x[,y]) | 通過鍵x訪問字典:若x存在返回對應的值;若x不存在返回none;若指定了y則x不存在返回y |
keys() | 返回鍵的列表 |
values() | 返回值的列表 |
items(x) | 返回元組組成的列表,每個元組由字典的鍵和相應值組成 |
copy() | 對字典進行淺復制 |
clear() | 刪除字典所有元素,保留空字典 |
addressbook1 = {"小華": "1872345", "小明": "1521055", "小芳": "1389909"}
addressbook1["小明"] # 通過key訪問value
addresbook1.get('小明') # 存在key時,返回對應的值
addresbook1.get('小紅') # 不存在key時,返回none
addresbook1.get('小紅', 110) # 不存在key時,返回指定的值
addresbook1.keys()
addresbook1.values()
addresbook1.items()
addresbook1.clear()
addresbook1
2.6.3 添加與修改
方法 | 含義 |
---|---|
update() | 更新信息:把一個字典的鍵值對添加到另一字典中去,若存在相同的key,則用后者覆蓋 |
pop() | 刪除指定key,並返回key對應的值 |
指定鍵為字典賦值 | 若鍵存在則修改鍵的值,若鍵不存在則新增鍵值對 |
值為可變數據類型 | 可進行相應數據類型的操作 |
addresbook1 = {"小明": "1521055", "小華": "1872345", "小芳": "1389909"}
addresbook1['小紅'] = '378598345' # 指定鍵為字典賦值
addresbook1
# 更新信息,若第一個字典的key在第二個字典也存在,則值以第二個字典的為准
addresbook1 = {"小明": "1521055", "小華": "1872345", "小芳": "1389909"}
addresbook2 = {"小華": "23462346", "小李": "0346246457"}
addresbook1.update(addresbook2)
addresbook1
# pop用法和作用同列表中pop一樣
addresbook1 = {"小明": "1521055", "小華": "1872345", "小芳": "1389909"}
addresbook1.pop('小明')
addresbook1
# 值可以為可變序列
addresbook1 = {"小明": "1521055", "小華": "1872345",
"小芳": [1389909, 1895436, 2748579]}
addresbook1
addresbook1["小芳"].append(9999999)
addresbook1
2.6.4 字典推導式
字典推導式語法類似於列表推導式,可快速生成符合指定條件的字典,只是外面是{ }。
# 生成鍵為序號,值為字符串的字典
{i: str(i) for i in range(5)}
# 將兩個序列關聯生成,生成字典
x = ['A', 'B', 'C', 'D']
y = ['a', 'b', 'b', 'd']
{x[i]: y[i] for i in range(len(x))}
{i: j for i, j in zip(x, y)}
# 隨機產生1000個字符,統計字符次數
import string # 導入string模塊
import random # 導入random模塊
x = string.ascii_letters + string.digits + string.punctuation # 生成字符串
y = [random.choice(x) for i in range(1000)] # 列表推導式
d = dict()
for ch in y:
d[ch] = d.get(ch, 0) + 1 # 不斷統計,更新鍵的值,之前沒有值則計1,有則取出加1
d
scores = {"Zhang San": 45, "Li Si": 78, "Wang Wu": 40, "Zhou Liu": 96,
"Zhao Qi": 65, "Sun Ba": 90, "Zheng Jiu": 78, "Wu Shi": 99, "Dong Shiyi": 60}
scores.values()
max(scores.values()) # 最高分
min(scores.values()) # 最低分
sum(scores.values())/len(scores) # 平均分
[name for name, score in scores.items() if score == max(scores.values())] # 最高分同學
[name for name, score in scores.items() if score > (
sum(scores.values())/len(scores))] # 高於平均分同學
2.7 集合(set)
集合最大的應用場景,就是「去重」。
2.7.1 創建
集合有兩種常見創建方式:
- 直接賦值創建
set(x)
函數創建
a = {1, 2, 3, 4} # 直接賦值創建
a
b = [5, 6, 7, 8] # set()函數創建
set(b)
2.7.2 基本操作
基本操作共有4種:交集(&)、並集(|)、差集(-)、補集(^)。
a = {1, 2, 3, 4}
b = {2, 3}
a & b
a | b
a - b
a ^ b
2.7.3 包含關系測試
包含關系測試常用於兩集合關系判斷,返回布爾值。
方法 | 含義 |
---|---|
x.issubset(y) | 判斷x是否為y子集 |
{x}.isdisjoint({y}) | 判斷x與y是否沒有交集 |
用>或<比較大小 | 判斷是否是子集 |
a = {1, 2, 3, 4}
b = {2, 3}
b.issubset(a)
b.isdisjoint(a)
a > b
b < a
2.7.4 常用函數和方法
方法 | 含義 |
---|---|
add(x) | 如果x不在集合中,將x增加到集合 |
clear() | 移除集合中所有元素 |
copy() | 淺拷貝 |
pop() | 隨機返回集合中的一個元素,若集合為空則報錯 |
discard(x) | 若x在集合中,移除x;若x不存在,不報錯 |
remove(x) | 若x在集合中,移除x;若x不存在,報錯 |
x in S | 判斷x是否是集合S元素 |
x not in S | 判斷x是否不是集合S元素 |
函數 | 含義 |
len() | 返回集合元素個數 |
a = {1, 2, 3, 4}
a.add(5)
a
b=a.copy() # 淺拷貝
b
3 not in b
len(b)