python | 可變數據類型-列表/字典/集合


 

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 類型轉換

字符串和列表經常互相轉換,具體方法是listjoin:

  • 函數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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM