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") ]
- 列表元素可以是不同類型
- 對象可以'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']
連結:
- 2. Built-in Functions # sorted, docs.python.org
- Sorting HOW TO, docs.python.org
迭代
[編輯]列表上的迭代:
列表上的只讀迭代,即遍歷列表的每個元素:
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
刪除
[編輯]在給定索引位置刪除元素 (參見#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)
連結:
- Remove items from a list while iterating, stackoverflow.com
聚合
[編輯]有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
連結:
- 8.17. copy — Shallow and deep copy operations at docs.python.org
清空
[編輯]清空一個列表:
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))
連結:
- How do you remove duplicates from a list? at python.org Programming FAQ
- Remove duplicates from a sequence (Python recipe) at activestate.com
- Removing duplicates in lists at stackoverflow.com
列表的成員函數
[編輯]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]
練習
[編輯]- Use a list comprehension to construct the list ['ab', 'ac', 'ad', 'bb', 'bc', 'bd'].
- Use a slice on the above list to construct the list ['ab', 'ad', 'bc'].
- Use a list comprehension to construct the list ['1a', '2a', '3a', '4a'].
- Simultaneously remove the element '2a' from the above list and print it.
- Copy the above list and add '2a' back into the list such that the original is still missing it.
- Use a list comprehension to construct the list ['abe', 'abf', 'ace', 'acf', 'ade', 'adf', 'bbe', 'bbf', 'bce', 'bcf', 'bde', 'bdf']
外部連結
[編輯]- Python documentation, chapter "Sequence Types" -- python.org
- Python Tutorial, chapter "Lists" -- python.org