跳至內容

Python/列表

維基教科書,自由的教學讀本

序列是Python中最基本的數據結構。序列中的每個元素都分配一個數字 - 它的位置,或索引,第一個索引是0,第二個索引是1,依此類推。

Python有6個內置的序列類型,但最常見的是列表和元組。

序列中元素的索引是基於0的。序列可以進行的操作有:索引,切片,加,乘,檢查成員。內置確定序列的長度以及確定最大和最小的元素的方法。

列表是最常用的Python數據類型,它可以作為一個方括號內的逗號分隔值出現。列表的元素不需要具有相同的類型

創建一個列表,只要把逗號分隔的不同的數據項使用方括號括起來即可。以使用append()方法來添加列表項。使用 del 語句來刪除列表的的元素。+ 號用於組合列表,* 號用於重複列表。


Python包含以下函數處理列表:

  • len(list) 列表元素個數
  • max(list) 返回列表元素最大值
  • min(list) 返回列表元素最小值
  • sum(list) 求和
  • list(seq) 將元組轉換為列表

list的方法:

  • list.append(obj) 在列表末尾添加新的對象
  • list.count(obj) 統計某個元素在列表中出現的次數
  • list.extend(seq) 在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表)
  • list.index(obj) 從列表中找出某個值第一個匹配項的索引位置
  • list.insert(index, obj) 將對象插入列表
  • list.pop(obj=list[-1]) 移除列表中的一個元素(默認最後一個元素),並且返回該元素的值
  • list.remove(obj) 移除列表中某個值的第一個匹配項
  • list.reverse() 反向列表中元素
  • list.sort([func]) 對原列表進行排序


創建二維矩陣,可用下述簡易方法,將需要的參數寫入 cols 和 rows :

list_2d = [[0 for col in range(cols)] for row in range(rows)]

一般示例

[編輯]

快速掌握列表:

list1 = []                      # 创建一个新的空列表
list2 = [1, 2, 3, "cat"]        # 有几个不同类型元素的新列表
list1.append("cat")             # 在列表的尾部增加一个元素
list1.extend(["dog", "mouse"])  # 增加几个元素
list1.insert(0, "fly")          # 在列表头部增加元素
list1[0:0] = ["cow", "doe"]     # 在列表头部添加元素
doe = list1.pop(1)              # 删除列表头部的元素
if "cat" in list1:              # 检测 "cat" 是否位于 list1 中(False)
  list1.remove("cat")           # 删除一个特定值
#list1.remove("elephant") - 没有这个元素:抛出错误
for item in list1:              # Iteration AKA for each item
  print (item)
print("Item count:", len(list1)) # Length AKA size AKA item count
list3 = [6, 7, 8, 9]
for i in range(0, len(list3)):  # Read-write iteration AKA for each item
  list3[i] += 1                 # Item access AKA element access by index
last = list3[-1]                # Last item
nextToLast = list3[-2]          # Next-to-last item
isempty = len(list3) == 0       # Test for emptiness
set1 = set(["cat", "dog"])      # Initialize set from a list
list4 = list(set1)              # Get a list from a set
list5 = list4[:]                # A shallow list copy
list4equal5 = list4 == list5    # True: same by value
list4refEqual5 = list4 is list5 # False: not same by reference
list6 = list4[:]
del list6[:]                    # Clear AKA empty AKA erase
list7 = [1, 2] + [2, 3, 4]      # Concatenation
print (list1, list2, list3, list4, list5, list6, list7)
print (list4equal5, list4refEqual5)
print (list3[1:3], list3[1:], list3[:2]) # Slices
print (max(list3 ), min(list3 ), sum(list3)) # Aggregates

print [x for x in range(10)]    # List comprehension
print [x for x in range(10) if x % 2 == 1]
print [x for x in range(10) if x % 2 == 1 if x < 5]
print [x + 1 for x in range(10) if x % 2 == 1]
print [x + y for x in '123' for y in 'abc']

創建List

[編輯]

有兩種方式創建List:賦值(靜態),列表理解(list comprehensions) ("主動的").

簡單創建

[編輯]

在一對方括號中創建:

[ 1,2,3,"This is a list",'c',Donkey("kong") ]
  1. 列表元素可以是不同類型
  2. 對象可以'on the fly'創建並增加到列表中,最後一項是Donkey類實例

創建一個列表,其元素值不是字面量:

a = 2
b = 3
myList = [a+b, b+a, len(["a","b"])]

列表理解

[編輯]

列表理解(list comprehension)描述了列表創建的過程。

例如,我們有一些單詞:

listOfWords = ["this","is","a","list","of","words"]

取每個單詞首字母創建一個列表:

>>> listOfWords = ["this","is","a","list","of","words"]
>>> items = [ word[0] for word in listOfWords ]
>>> print (items)
['t', 'i', 'a', 'l', 'o', 'w']

列表理解支持for語句多次出現:

>>> item = [x+y for x in 'cat' for y in 'pot']
>>> print (item)
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']

列表理解支持if語句,只有滿足特別條件的才能加入列表中:

>>> print [x+y for x in 'cat' for y in 'pot']
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']
>>> print [x+y for x in 'cat' for y in 'pot' if x != 't' and y != 'o' ]
['cp', 'ct', 'ap', 'at']
>>> print [x+y for x in 'cat' for y in 'pot' if x != 't' or y != 'o' ]
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'tt']

Python 2.x中,列表理解不定義一個作用域。列表理解中綁定求值的變量再在求值完成後保持該綁定。Python 3.x中這些是局部變量:

>>> print x, y                         #Input to python version 2
t t                                    #Output using python 2

>>> print(x, y)                        #Input to python version 3
NameError: name 'x' is not defined     #Python 3 returns an error because x and y were not leaked

列表理解可以使用zip或itertools.izip處理多個列表:

[a - b for (a,b) in zip((1,2,3), (1,2,3))]  # will return [0, 0, 0]

列表快捷創建

[編輯]

創建一個列表給定大小,每個元素被初始化:

>>> zeros=[0]*5
>>> print (zeros)
[0, 0, 0, 0, 0]

這種方式適用於任何數據類型:

>>> foos=['foo']*3
>>> print foos
['foo', 'foo', 'foo']

有一些警告:當用這種乘法形式建造列表時,Python使用每項的引用。這會造成修改其中一項帶來所有項都改變的副作用。特別是多維數組:

listoflists=[ [0]*4 ] *5

這可以,但可能不是你所期望的:

>>> listoflists=[ [0]*4 ] *5
>>> print listoflists
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> listoflists[0][2]=1
>>> print listoflists
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]

Python使用內層列表的引用作為外層列表的元素。也可以用如下方式重演該問題:

>>> innerlist=[0]*4
>>> listoflists=[innerlist]*5
>>> print listoflists
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> innerlist[2]=1
>>> print listoflists
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]

可以用列表理解來避免上述副作用:

>>> listoflists=[[0]*4 for i in range(5)]
>>> print listoflists
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> listoflists[0][2]=1
>>> print listoflists
[[0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

列表的尺寸

[編輯]

使用內建的len()函數:

>>> len([1,2,3])
3
>>> a = [1,2,3,4]
>>> len( a )
4

組合多個列表

[編輯]

只需要把它們加起來:

>>> [1,2] + [3,4]
[1, 2, 3, 4]

另一種方法是使用列表的成員函數extend. 如果在lambda表達式內部組合多個列表, extend是正確的方法。

>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a.extend(b)
>>> print a
[1, 2, 3, 4, 5, 6]

列表追加一個元素,用列表的成員函數append

>>> p=[1,2]
>>> p.append([3,4])
>>> p
[1, 2, [3, 4]]
>>> # or
>>> print p
[1, 2, [3, 4]]

列表的切片

[編輯]

連續切片

[編輯]

類似於strings,列表可以被索引、切片:

>>> list = [2, 4, "usurp", 9.0, "n"]
>>> list[2]
'usurp'
>>> list[3:]
[9.0, 'n']

不同於字符串,對列表的切片可以賦新值:

>>> list[1] = 17
>>> list
[2, 17, 'usurp', 9.0, 'n']

甚至可以給列表的切片賦以具有不等長度的新值:

>>> list[1:4] = ["opportunistic", "elk"]
>>> list
[2, 'opportunistic', 'elk', 'n']

可以在列表的開頭插入新的值序列:

>>> list[:0] = [3.14, 2.71]
>>> list
[3.14, 2.71, 2, 'opportunistic', 'elk', 'n']

類似的,也可以在列表末尾追加新的值序列:

>>> list[len(list):] = ['four', 'score']
>>> list
[3.14, 2.71, 2, 'opportunistic', 'elk', 'n', 'four', 'score']

可以徹底改編列表內容:

>>> list[:] = ['new', 'list', 'contents']
>>> list
['new', 'list', 'contents']

列表賦值語句的右端可以是任何可迭代類型:

>>> list[:2] = ('element',('t',),[])
>>> list
['element', ('t',), [], 'contents']

切片創造了列表的新的拷貝:

>>> original = [1, 'element', []]
>>> list_copy = original[:]
>>> list_copy
[1, 'element', []]
>>> list_copy.append('new element')
>>> list_copy
[1, 'element', [], 'new element']
>>> original
[1, 'element', []]

注意:這是淺拷貝,是與最初列表相同的引用,對易變類型要格外小心:

>>> list_copy[2].append('something')
>>> original
[1, 'element', ['something']]

不連續切片

[編輯]

使用運算符 lower_limit:upper_limit:step可以做不連續切片:

>>> list = [i for i in range(10) ]
>>> list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list[::2]
[0, 2, 4, 6, 8]
>>> list[1:7:2]
[1, 3, 5]

比較列表

[編輯]

列表可以做相等比較:

>>> [1,2] == [1,2]
True
>>> [1,2] == [3,4]
False

列表也可以用小於運算符做詞典序比較:

>>> [1,2] < [2,1]
True
>>> [2,2] < [2,1]
False
>>> ["a","b"] < ["b","a"]
True

排序列表

[編輯]

概覽:

list1 = [2, 3, 1, 'a', 'B']
list1.sort()                                   # list1 gets modified, case sensitive
list2 = sorted(list1)                          # list1 is unmodified; since Python 2.4
list3 = sorted(list1, key=lambda x: x.lower()) # case insensitive ; will give error as not all elements of list are strings and .lower() is not applicable
list4 = sorted(list1, reverse=True)            # Reverse sorting order: descending
print list1, list2, list3, list4

列表的成員函數sort做原地排序,返回值為None:

>>> list1 = [2, 3, 1, 'a', 'b']
>>> list1.sort()
>>> list1
[1, 2, 3, 'a', 'b']

Python 2.4及以上版本提供一些參數:

  • sort(cmp,key,reverse)
    • cmp : 指定一個定製的比較函數,這個函數接收兩個參數(元素),如果第一個參數小於第二個參數,返回一個負數;如果第一個參數等於第二個參數,返回零;如果第一個參數大於第二個參數,返回一個正數。默認值為None。
    • key : 這是一個函數,傳入key值,列表根據該函數返回值做排序。
    • reverse : sort(reverse=True)或sort(reverse=False)

Python內置函數sorted()不是原地排序,而是返回一個有序的列表:

>>> list1 = [5, 2, 3, 'q', 'p']
>>> sorted(list1)
[2, 3, 5, 'p', 'q']
>>> list1
[5, 2, 3, 'q', 'p']

連結:

迭代

[編輯]

列表上的迭代:

列表上的只讀迭代,即遍歷列表的每個元素:

list1 = [1, 2, 3, 4]
for item in list1:
  print item

列表上的可寫迭代:

list1 = [1, 2, 3, 4]
for i in range(0, len(list1)):
  list1[i]+=1 # Modify the item at an index as you see fit
print list

列表上迭代,步長不為1:

for i in range(1, 13+1, 3): # For i=1 to 13 step 3
  print i
for i in range(10, 5-1, -1): # For i=10 to 5 step -1
  print i

滿足特定條件(過濾)的迭代:

for item in list:
  if not condition(item):
    continue
  print item

參見 Python/Loops#For_Loops.

刪除

[編輯]

在給定索引位置刪除元素 (參見#pop(i)):

list1 = [1, 2, 3, 4]
list1.pop() # Remove the last item
list1.pop(0) # Remove the first item , which is the item at index 0
print list1

list1 = [1, 2, 3, 4]
del list1[1] # Remove the 2nd element; an alternative to list.pop(1)
print list1

按值刪除元素:

list1 = ["a", "a", "b"]
list1.remove("a") # Removes only the 1st occurrence of "a"
print list1

保留滿足條件的元素,刪除不滿足條件的元素:

list1 = [1, 2, 3, 4]
newlist = [item for item in list1 if item > 2]
print newlist

使用"[:]":

list1 = [1, 2, 3, 4]
sameList = list1
list1[:] = [item for item in list1 if item > 2]
print sameList, sameList is list1

把條件作為獨立的函數:

list1 = [1, 2, 3, 4]
def keepingCondition(item):
  return item > 2
sameList = list1
list1[:] = [item for item in list1 if keepingCondition(item)]
print sameList, sameList is list1

迭代列表同時做刪除要特別小心索引的使用:

list1 = [1, 2, 3, 4]
index = len(list1)
while index > 0:
  index -= 1
  if not list1[index] < 2:
    list1.pop(index)

連結:

聚合

[編輯]

有3個內建的算術聚合函數:minimum, maximum, sum:

list = [1, 2, 3, 4]
print max(list), min(list), sum(list)
average = sum(list) / float(len(list)) # Provided the list is non-empty
# The float above ensures the division is a float one rather than integer one.
print average
list = ["aa", "ab"]
print max(list), min(list) # Prints "ab aa"

複製

[編輯]

淺複製:

list1= [1, 'element']
list2 = list1[:] # Copy using "[:]"
list2[0] = 2 # Only affects list2, not list1
print list1[0] # Displays 1

#对比
list1 = [1, 'element']
list2 = list1
list2[0] = 2 # Modifies the original list
print list1[0] # Displays 2

下例可以說明淺拷貝:

list1 = [1, [2, 3]] # Notice the second item being a nested list
list2 = list1[:] # A shallow copy
list2[1][0] = 4 # Modifies the 2nd item of list1 as well
print list1[1][0] # Displays 4 rather than 2

深拷貝例子:

import copy
list1 = [1, [2, 3]] # Notice the second item being a nested list
list2 = copy.deepcopy(list1) # A deep copy
list2[1][0] = 4 # Leaves the 2nd item of list1 unmodified
print list1[1][0] # Displays 2

連結:

清空

[編輯]

清空一個列表:

del list1[:] # Clear a list
list1 = []   # Not really clear but rather assign to a new empty list

注意不同清空方式對列表作為函數參數的影響:

def workingClear(ilist):
  del ilist[:]
def brokenClear(ilist):
  ilist = [] # Lets ilist point to a new list, losing the reference to the argument list
list1=[1, 2]; workingClear(list1); print (list1)
list1=[1, 2]; brokenClear(list1); print (list1)

刪除冗餘元素

[編輯]

Removing duplicate items from a list (keeping only unique items) can be achieved as follows.

如果列表元素是可哈希的,使用列表理解很快:

list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
seen = {}
list1[:] = [seen.setdefault(e, e) for e in list1 if e not in seen]

如果列表元素是可哈希的,使用索引迭代會慢一些:

list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
seen = set()
for i in range(len(list1) - 1, -1, -1):
  if list1[i] in seen:
    list1.pop(i)
  seen.add(list1[i])

如果某些元素是不可哈希的,可以把所有訪問過的元素放在一個列表中:

list1 = [1, 4, 4, ["a", "b"], 5, ["a", "b"], 3, 2, 3, 2, 1]
seen = []
for i in range(len(list1) - 1, -1, -1):
  if list1[i] in seen:
    list1.pop(i)
  seen.append(list1[i])

如果每個元素是可哈希的且保持元素的序無關緊要:

list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
list1[:] = list(set(list1))  # Modify list1
list2 = list(set(list1))

連結:

列表的成員函數

[編輯]

append(x)

[編輯]

在列表尾部追加:

>>> list = [1, 2, 3]
>>> list.append(4)
>>> list
[1, 2, 3, 4]

pop(i)

[編輯]

刪除索引位置的元素。缺省刪除尾部元素

>>> list = [1, 2, 3, 4]
>>> a = list.pop(0)
>>> list
[2, 3, 4]
>>> a
1
>>> b = list.pop()
>>>list
[2, 3]
>>> b
4

運算符

[編輯]

連接兩個列表。

把一個列表複製多次連接起來。

in

[編輯]

運算符'in'有兩種用途:在for循環中遍歷每個元素;或者對一個值是否出現在列表種給出判斷結果True或False

>>> list = [1, 2, 3, 4]
>>> if 3 in list:
>>>    ....
>>> l = [0, 1, 2, 3, 4]
>>> 3 in l
True
>>> 18 in l
False
>>>for x in l:
>>>    print x
0
1
2
3
4

差集

[編輯]

兩個列表的差集,需要迭代:

a = [0, 1, 2, 3, 4, 4]
b = [1, 2, 3, 4, 4, 5]
print ([item for item in a if item not in b])
# [0]

交集

[編輯]

兩個列表的交集,減去差集:

a = [0, 1, 2, 3, 4, 4]
b = [1, 2, 3, 4, 4, 5]
dif = [item for item in a if item not in b]
print [item for item in a if item not in dif]
# [1, 2, 3, 4, 4]

練習

[編輯]
  1. Use a list comprehension to construct the list ['ab', 'ac', 'ad', 'bb', 'bc', 'bd'].
  2. Use a slice on the above list to construct the list ['ab', 'ad', 'bc'].
  3. Use a list comprehension to construct the list ['1a', '2a', '3a', '4a'].
  4. Simultaneously remove the element '2a' from the above list and print it.
  5. Copy the above list and add '2a' back into the list such that the original is still missing it.
  6. Use a list comprehension to construct the list ['abe', 'abf', 'ace', 'acf', 'ade', 'adf', 'bbe', 'bbf', 'bce', 'bcf', 'bde', 'bdf']

外部連結

[編輯]