Python list列表使用技巧及注意事項

2020-07-16 10:05:04
前面章節介紹了很多關於 list 列表的操作函數,細心的讀者可能會發現,有很多操作函數的功能非常相似。例如,增加元素功能的函數有 append() 和 extend(),刪除元素功能的有 clear()、 remove()、pop() 和 del 關鍵字。

本節將通過範例演示的方式來明確各個函數的用法,以及某些函數之間的區別和在使用時的一些注意事項。

Python list新增元素的方法及區別

定義兩個列表(分別是 list1 和 list3),並分別使用 +、extend()、append() 對這兩個 list 進行操作,其操作的結果賦值給 l2。範例程式碼如下:
tt = 'hello'
#定義一個包含多個型別的 list
list1 = [1,4,tt,3.4,"yes",[1,2]]
print(list1,id(list1))

print("1.----------------")

#比較 list 中新增元素的幾種方法的用法和區別
list3 = [6,7]
l2 = list1 + list3
print(l2,id(l2))

print("2.----------------")

l2 = list1.extend(list3)
print(l2,id(l2))
print(list1,id(list1))

print("3.----------------")

l2 = list1.append(list3)
print(l2,id(l2))
print(list1,id(list1))
輸出結果為:

[1, 4, 'hello', 3.4, 'yes', [1, 2]] 2251638471496
1.----------------
[1, 4, 'hello', 3.4, 'yes', [1, 2], 6, 7] 2251645237064
2.----------------
None 1792287952
[1, 4, 'hello', 3.4, 'yes', [1, 2], 6, 7] 2251638471496
3.----------------
None 1792287952
[1, 4, 'hello', 3.4, 'yes', [1, 2], 6, 7, [6, 7]] 2251638471496

根據輸出結果,可以分析出以下幾個結論:
  1. 使用“+”號連線的列表,是將 list3 中的元素放在 list 的後面得到的 l2。並且 l2 的記憶體地址值與 list1 並不一樣,這表明 l2 是一個重新生成的列表。
  2. 使用 extend 處理後得到的 l2 是 none。表明 extend 沒有返回值,並不能使用鏈式表示式。即 extend 千萬不能放在等式的右側,這是程式設計時常犯的錯誤,一定要引起注意。
  3. extend 處理之後, list1 的內容與使用“+”號生成的 l2 是一樣的。但 list1 的地址在操作前後並沒有變化,這表明 extend 的處理僅僅是改變了 list1,而沒有重新建立一個 list。從這個角度來看,extend 的效率要高於“+”號。
  4. 從 append 的結果可以看出,append 的作用是將 list3 整體當成一個元素追加到 list1 後面,這與 extend 和“+”號的功能完全不同,這一點也需要注意。

Python list刪除操作

接下來演示有關 del 的基本用法,範例程式碼如下:
tt = 'hello'
#定義一個包含多個型別的 list
list1 = [1,4,tt,3.4,"yes",[1,2]]
print(list1)
del list1[2:5]
print(list1)
del list1[2]
print(list1)
輸出結果為:

[1, 4, 'hello', 3.4, 'yes', [1, 2]]
[1, 4, [1, 2]]
[1, 4]

這 3 行輸出分別是 list1 的原始內容、刪除一部分切片內容、刪除指定索引內容。可以看到,del 關鍵字按照指定的位置刪掉了指定的內容。

需要注意的是,在使用 del 關鍵字時,一定要搞清楚,刪除的到底是變數還是資料。例如,下面程式碼演示和刪除變數的方法:
tt = 'hello'
#定義一個包含多個型別的 list
list1 = [1,4,tt,3.4,"yes",[1,2]]
l2 = list1
print(id(l2),id(list1))
del list1
print(l2)
print(list1)
執行結果如下:

1765451922248 1765451922248
[1, 4, 'hello', 3.4, 'yes', [1, 2]]
Traceback (most recent call last):
  File "C:UsersmengmaDesktopdemo.py", line 8, in <module>
    print(list1)
NameError: name 'list1' is not defined

第一行輸出的內容是 l2 和 list1 的地址,可以看到它們是相同的,說明 l2 和 list1 之間的賦值僅僅是傳遞記憶體地址。接下來將 list1 刪掉,並列印 l2,可以看到,l2 所指向的記憶體資料還是存在的,這表明 del 刪除 list1 時僅僅是銷毀了變數 list1,並沒有刪除指定的資料。

除了刪除變數,其他的刪除都是刪除資料,比如將列表中資料全部清空,實現程式碼如下:
tt = 'hello'
#定義一個包含多個型別的 list
list1 = [1,4,tt,3.4,"yes",[1,2]]
l2 = list1
l3 = l2
del l2[:]
print(l2)
print(l3)
輸出結果為:

[]
[]

可以看到,l3 和 l2 執行同樣的記憶體地址,當 l2 被清空之後,l3 的內容也被清空了。這表明記憶體中的資料真正改變了。

另外,在實際過程中,即便使用 del 關鍵字刪除了指定變數,且該變數所佔用的記憶體再沒有其他變數使用,此記憶體空間也不會真正地被系統回收並進行二次使用,它只是會被標記為無效記憶體。

如果想讓系統回收這些可用的記憶體,需要借助 gc 庫中的 collect() 函數。例如:
#引入gc庫
import gc
tt = 'hello'
#定義一個包含多個型別的 list
list1 = [1,4,tt,3.4,"yes",[1,2]]
del list1
#回收記憶體地址
gc.collect()
前面我們在《Python快取機制》一節講過,系統為了提升效能,會將一部分變數駐留在記憶體中。這個機制對於,多執行緒並行時程式產生大量佔用記憶體的變數無法得到釋放,或者某些不再需要使用的全域性變數占用著大的記憶體,導致後續執行中出現記憶體不足的情況,此時就可以使用 del 關鍵字來回收記憶體,使系統的效能得以提升。同時,它可以為團隊省去擴充大量記憶體的成本。