Python核心數據類型——列表
列表是一個任意類型的對象的位置相關的有序集合,它沒有固定的大小。大小可變的,通過偏移量進行賦值以及其他各種列表的方法進行調用,能夠修改列表。其他更多的功能可以查閱python的標准手冊,或者運行help(list)或dir(list)查看list方法的完整清單。
- 任意對象的有序集合:從功能上看,列表是收集其他對象的地方,同時列表所包含的每一項都保持了從左到右的位置順序。
- 通過偏移讀取:可以通過列表對象的偏移對其進行索引,從而讀取對象的某一部分內容。由於列表的每一項都是有序的,所以可以執行諸如分片、合並之類任務。
- 可變長度、異構以及任意嵌套:與字符串不同的是,列表可以實地的增長或者縮短(可變長度),並且可以包含任何類型的對象而不僅僅是包含有單個字符的字符串(異構)。列表能夠包含其他復雜對象,又能夠支持任意嵌套,可以創建列表的子列表的子列表等。
- 屬於可變序列的分類:列表支持在原處修改,列表合並和分片操作是返回新的列表。
- 對象引用數組:從技術上看,Python列表包含了零個或多個其他對象的引用。
創建
>>> L = list() >>> L1 = [] >>> type(L),type(L1) (<class 'list'>, <class 'list'>)
常用列表常量和操作
操作 | 解釋 |
L = [] | 一個空列表 |
L = [0,1,2,3] | 四項:索引為0到3 |
L = [‘abc’,[‘def’,’ghi’]] | 嵌套子列表 |
L = list(‘spam’),L = list(rang(-4,4)) | 可迭代像的列表,連續整數的列表 |
L[i],L[i][j],L[i:j],len(L) | 索引,索引的索引,分片,求長度 |
L1 + L2 | 合並 |
L * 3 | 重復 |
for x in L : print(x) , 3 in L | 迭代,成員關系 |
L.append(4),L.extend([5,6,7]),L.insert(I,x),L.index(1),L.count(x),L.sort(),L.reverse() | 方法:增長,排序,搜索,插入,翻轉等 |
del L[k],del L[i:j],L.pop(),L.remove(2),L[i:j] = [] | 方法:刪除縮短 |
L[i] = 1,L[i:j] = [4,5,6] | 索引賦值,分片賦值 |
L = [x ** 2 for x in range(5)],list(map(ord,’spam’)) | 列表解析 |
>>> str([1,2])+'34' '[1, 2]34' >>> [1,2]+list("34") [1, 2, '3', '4']
序列操作
可以對列表進行索引、切片等操作,就像字符串所做的操作那樣
>>> L = [123,'spam',1.23] >>> len(L) #列表長度 3 >>> L[0] #通過索引查找元素 123 >>> L[:-1] #切片返回新列表 [123, 'spam'] >>> L + [4,5,6] #多個列表合並為新的列表 [123, 'spam', 1.23, 4, 5, 6] >>> L #原列表未改變 [123, 'spam', 1.23]
原處修改列表
列表是可變的,它們支持原地改變列表對象的操作。當使用列表的時候,可以將它賦值給一個特定項(偏移)或整個片段(分片)來改變它的內容:
>>> L = ['spam','Spam',"SPAM"] >>> L[1] = 'eggs' >>> L ['spam', 'eggs', 'SPAM'] >>> L[0:2] = ['eat','more'] >>> L ['eat', 'more', 'SPAM']
索引和分片的賦值都是原地修改,它們對列表進行直接修改,而不是生成一個新的列表作為結果。
類型特定的操作
Python列表與其他語言中的數組有些類似,但要強大得多。其中一個方面就是列表沒有固定的約束。如上例子中,列表可以包含不同類型的對象(整數、字符串、浮點數等)。
>>> L = [123,'spam',1.23] >>> L.append('NI') #通過append方法在列表末尾增加元素項 >>> L [123, 'spam', 1.23, 'NI'] >>> L.pop(2) #pop方法移除索引上的元素項 1.23 >>> L [123, 'spam', 'NI'] >>> M = ['bb','aa','cc'] >>> M.sort() #sort方法,默認按升序對列表進行排序 >>> M ['aa', 'bb', 'cc'] >>> M.reverse() #reverse方法進行翻轉 >>> M ['cc', 'bb', 'aa']
邊界檢查
雖然列表沒有固定的大小,Python扔不允許引用不存在的元素,超出列表末尾之外的索引總是會報錯,對列表末尾范圍之外的賦值也報錯。
>>> L [123, 'spam', 'NI'] >>> L[99] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range >>> L[99] = 1 Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list assignment index out of range
嵌套
Python核心數據類型的一個優秀特性是它們支持任意的嵌套。能夠以任意的組合對其進行嵌套,並可以多個層次進行嵌套(如:一個列表可以包含一個字典,並在這個字典中包含另外一個列表等)。
>>> M = [[1,2,3],[4,5,6],[7,8,9]] >>> M [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> M[1] [4, 5, 6] >>> M[1][2] 6
列表解析
列表解析表達式(list comperhension expression)提供了一種處理像矩陣這樣結構的強大工具。通過簡單的索引可以獲取行,使用列表解析可以同樣簡單地獲取列。列表解析是通過對序列中的每一項運行一個表達式來創建一個新列表的方法,每次一個,從左到右。列表解析是編寫在方括號中(提醒你在創建列表這個事實),並且由使用了同一個變量名的表達式和循環結構組成。
>>> col2 = [row[1] for row in M] >>> col2 [2, 5, 8] >>> M [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> [row[1] + 1 for row in M] [3, 6, 9] >>> [row[1] for row in M if row[1] % 2 == 0] [2, 8] >>> diag = [M[i][i] for i in [0,1,2]] >>> diag [1, 5, 9] >>> doubles = [c * 2 for c in 'spam'] >>> doubles ['ss', 'pp', 'aa', 'mm'] >>> list(map(sum,M)) [6, 15, 24] >>> [ord(x) for x in 'spam'] [115, 112, 97, 109]
列表函數
函數 | 描述 |
len(list) | 列表元素個數 |
max(list) | 返回列表元素最大值 |
min(list) | 返回列表元素最小值 |
列表方法
list.append(obj) | 用於在列表末尾添加新的對象。該方法無返回值,但是會修改原來的列表。obj -- 添加到列表末尾的對象。 |
list.count(obj) | 返回元素在列表中出現的次數。obj -- 列表中統計的對象。 |
list.extend(seq) | 用於在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表)。該方法沒有返回值,但會在已存在的列表中添加新的列表內容。seq -- 元素列表。 |
list.index(obj) | 從列表中找出某個值第一個匹配項的索引位置。返回查找對象的索引位置,如果沒有找到對象則拋出異常。obj -- 查找的對象。 |
list.insert(index, obj) | 將指定對象插入列表的指定位置。index -- 對象 obj 需要插入的索引位置。obj -- 要插入列表中的對象。 |
list.pop(index=list[-1]) | 移除列表中的一個元素(默認最后一個元素),並且返回該元素的值。index-- 可選參數,要移除列表元素的對象的索引位置。 |
list.remove(obj) | 沒有返回值但是會移除列表中的某個值的第一個匹配項。obj -- 列表中要移除的對象。 |
list.reverse() | 沒有返回值,但是會對列表的元素進行反向排序。 |
list.sort([func]) | 對原列表進行排序,如果指定參數,則使用比較函數指定的比較函數。沒有返回值。func -- 可選參數, 如果指定了該參數會使用該參數的方法進行排序。 |
Python核心數據類型——字典
除了列表以外,字典(dictionary)是Python之中最靈活的內置數據結構類型。列表是有序的,字典是無序的,他們主要的差別是:字典當中的元素是通過鍵來存取的,列表是通過偏移量存取。
- 通過鍵而不是偏移量來讀取
- 任意對象的無序集合:與列表不同,保存在字典中的項並沒有特定的順序。
- 可變長、異構、任意嵌套:與列表相似,字典可以在原處增長或縮短(無需生成一份拷貝)。他們可以包含任何類型的對象,而且他們支持任意深度的嵌套(可以包含列表和其他的字典等)。
- 屬於可變映射類型:通過給索引賦值,字典可以在原處修改(可變),但不支持用於字符串和列表中的序列操作。因為字典是無序集合,所以根據固定順序進行操作是行不通的(例如合並和分片操作)。字典是唯一內置的映射類型(鍵映射到值得對象)。
- 對象引用表(散列表):字典是支持鍵讀取的無序對象引用表。從本質上講,字典是作為散列表(支持快速檢索的數據結構)來實現的,一開始很小,並根據要求而增長。Python采用最優化的散列算法來尋找鍵,因此搜索是很快速的。和列表一樣,字典存儲的是對象引用(不是拷貝)。
dir(dict)或者help(dict)可以得到完整的dict類型操作清單。當寫成常量表達式時,字典以一系列“鍵:值(key:value)”形式寫出來,用逗號隔開,用大括號括起來。
常見字典常量和操作
操作 | 解釋 |
D = {} | 空字典 |
D = {‘spam’:2,”eggs”:3} | 兩項目字典 |
D = {‘food’:{‘ham’:1,’egg’:2}} | 嵌套字典 |
D = dict.fromkeys([‘a’,’b’]) | 其他構造技術D = {'b': None, 'a': None} |
D = dict(zip(keyslist,valslist)) | 關鍵字、對應的鍵、值 |
D = dict(name=’bob’,age=42) | D = {'age': 42, 'name': 'bob'} |
D['eggs'],D['food']['ham'] | 以鍵進行索引運算 |
‘eggs’in D | 成員判斷,鍵存在測試 |
D.keys() | 方法:鍵 |
D.values() | 值 |
D.items() | 鍵+值 |
D.copy() | 淺copy復制 |
D.get(key,default) | 默認 |
D.update(D2) | 合並 |
D.pop(key) | 刪除 |
len(D) | 長度(存儲的鍵的數目) |
D[key] = 42 | 新增/修改鍵 |
del D[key] | 根據鍵刪除項目 |
list(D.keys()) | 3.0+的D.keys()是生成可迭代視圖,要顯示需要放在list中 |
D1.keys() & D2.keys() | 與操作,結果為鍵的set集合 |
D={x:x*2 for x in range(10)} | 字典解析 |
字典通過鍵進行索引,被嵌套的字典項是由一系列索引(方括號的鍵)表示的。當Python創建字典時,會按照任意所選從左到右的順序來存儲項。要取回一個值,需要提供相應的鍵。
字典的基本操作
>>> D = {'spam':2,'ham':1,'eggs':3} >>> D['spam'] 2 >>> D {'ham': 1, 'spam': 2, 'eggs': 3} >>> len(D) 3 >>> 'ham' in D #與2.0+的has_key()方法相同 True >>> list(D.keys()) ['ham', 'spam', 'eggs']
原處修改字典
可以在原處對字典進行修改、擴展以及縮短而不需要生成新的字典。
>>> D {'ham': 1, 'spam': 2, 'eggs': 3} >>> D['ham'] = ['gill','bake','fry'] #修改 >>> D {'ham': ['gill', 'bake', 'fry'], 'spam': 2, 'eggs': 3} >>> del D['eggs'] #刪除 >>> D {'ham': ['gill', 'bake', 'fry'], 'spam': 2} >>> D['brunch'] = 'bacon'#增加 >>> D {'ham': ['gill', 'bake', 'fry'], 'spam': 2, 'brunch': 'bacon'}
其他字典方法
>>> D = {'spam':2,'ham':1,'eggs':3} >>> list(D.keys()) ['ham', 'spam', 'eggs'] >>> list(D.values()) [1, 2, 3] >>> list(D.items()) [('ham', 1), ('spam', 2), ('eggs', 3)] >>> D.get('spam') 2 >>> print(D.get('toast'))#不存在的key返回none值 None >>> D.get('toast',88)#添加一個默認值時,不存在的可以會顯示為默認值 88 >>> D {'ham': 1, 'spam': 2, 'eggs': 3} >>> D2 = {'toast':4,'muffin':5} >>> D.update(D2) #合並字典D2到D字典中 >>> D {'ham': 1, 'spam': 2, 'toast': 4, 'muffin': 5, 'eggs': 3} #字典pop方法通過鍵刪除,並返回刪除的值 >>> D.pop('muffin') 5 >>> D.pop('toast') 4 >>> D {'ham': 1, 'spam': 2, 'eggs': 3} #不同於列表的默認刪除最后一個或刪除提供的偏移值 >>> L = ['aa','bb','cc','dd'] >>> L.pop() 'dd' >>> L ['aa', 'bb', 'cc'] >>> L.pop(1) 'bb' >>> L ['aa', 'cc']
字典用法注意
- 序列運算無效。字典是映射機制,不是序列。因為字典元素沒有順序的概念,類似串聯(有序合並)和分片(提取相鄰片段)這樣的運算是不能用的。
- 對新索引賦值會添加項。當編寫字典常量是(鍵是嵌套與常量本身的),或者向現有字典對象的新鍵賦值時,都會生成鍵。
- 鍵不一定總是字符串。任何不可變對象都可以作為鍵。
字典解析
字典解析隱式地運行一個循環,根據每次迭代收集表達式的鍵/值結果,使它們來填充一個新的字典。
>>> list(zip(['a','b','c'],[1,2,3])) #zip函數將keys和values成對 [('a', 1), ('b', 2), ('c', 3)] >>> d = dict(zip(['a','b','c'],[1,2,3])) #zip函數是一個單個調用中從鍵和值得列表來構建一個字典的方式之一 >>> d {'b': 2, 'c': 3, 'a': 1} #字典解析表達式創建字典 >>> d = {k:v for (k,v) in zip(['a','b','c'],[1,2,3])} >>> d {'b': 2, 'c': 3, 'a': 1} >>> {x:x ** 2 for x in [1,2,3]} {1: 1, 2: 4, 3: 9} >>> {x:x ** 2 for x in [1,2,3,4]} {1: 1, 2: 4, 3: 9, 4: 16} >>> {c:c * 4 for c in 'spam'} {'p': 'pppp', 'm': 'mmmm', 'a': 'aaaa', 's': 'ssss'} >>> {c.lower():c + '!' for c in ['SPAM','EGGS','HAM']} {'ham': 'HAM!', 'spam': 'SPAM!', 'eggs': 'EGGS!'} #dict.fromkeys()創建字典與字典解析比較 >>> dict.fromkeys(['a','b','c'],0) {'b': 0, 'c': 0, 'a': 0} >>> {k:0 for k in ['a','b','c']} {'b': 0, 'c': 0, 'a': 0} >>> dict.fromkeys('spam') {'p': None, 'm': None, 'a': None, 's': None} >>> {k:None for k in 'spam'} {'p': None, 'm': None, 'a': None, 's': None}
字典視圖
python3.0+中,字典的keys、values和items都返回視圖對象。視圖對象是可迭代的,這就意味着對象每次產生一個結果項,而不是在內存中立即產生的結果列表。除了可迭代,字典視圖還保持了字典成分的最初順序,反映字典未來的修改,並且能夠支持集合的操作,另一方面,它們不是列表,並且不支持像索引和列表的sort方法這樣的操作。
>>> D = dict(a=1,b=2,c=3) >>> D {'b': 2, 'c': 3, 'a': 1} >>> k = D.keys() >>> k dict_keys(['b', 'c', 'a']) >>> list(k) ['b', 'c', 'a'] >>> v = d.values() >>> v dict_values([2, 3, 1]) >>> list(v) [2, 3, 1] >>> list(d.items()) [('b', 2), ('c', 3), ('a', 1)] >>> k[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'dict_keys' object does not support indexing >>> list(k)[0] 'b'
可以使用for循環來迫使迭代對象每次迭代上產生一個結果:
>>> for k in D.keys():print(k) ... b c a >>> for k in D: print(k) #兩種寫法一樣 ... b c a
python3.0+ 字典視圖並非創建后不能改變——它們可以動態地反映在視圖對象創建之后對字典做出的修改:
>>> D {'b': 2, 'c': 3, 'a': 1} >>> K = D.keys() >>> V = D.values() >>> list(K) ['b', 'c', 'a'] >>> list(V) [2, 3, 1] >>> del D['b'] >>> D {'c': 3, 'a': 1} >>> list(K) ['c', 'a'] >>> list(V) [3, 1]
字典視圖和集合:
keys方法所返回的Python3.0+的視圖對象類似於集合(set),並且支持交集和並集等常見的集合操作;values視圖卻不一樣,因為它們不是唯一的;但items結果卻是,如果(key,value)對是唯一的並且可散列的話。由於集合的行為很像是無值的字典,這是一種符合邏輯的對稱。就像字典一樣,集合的項是無序的、唯一的並且不可變的。
>>> K | {'x':4} {'x', 'c', 'a'} >>> V & {'x':4} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict' >>> V & {'x':4}.values() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict_values' >>> D = dict(a=1,b=2,c=3) >>> D {'b': 2, 'c': 3, 'a': 1} >>> D.keys() & D.keys() {'b', 'c', 'a'} >>> D.keys() & 'b' {'b'} >>> D.keys() & {'b':1} {'b'} >>> D.keys() | {'b','c','d'} {'b', 'c', 'd', 'a'}
如果字典項視圖是可散列的話,它們是類似於集合的——也就是說,如果它們只包含不可變的對象的話:
>>> D = {'a':1} >>> list(D.items()) [('a', 1)] >>> D.items() | D.keys() {('a', 1), 'a'} >>> D.items() | D {('a', 1), 'a'} >>> D.items() | {('c',3),('d',4)} {('d', 4), ('a', 1), ('c', 3)} >>> dict(D.items() | {('c',3),('d',4)}) {'c': 3, 'a': 1, 'd': 4}
排序字典鍵
由於keys不會返回一個列表,必須要么手動轉換為一個列表,要么在一個鍵視圖或字典自身上用sorted調用:
>>> D = {'a':1,'b':2,'c':3} >>> D {'b': 2, 'c': 3, 'a': 1} >>> Ks = D.keys() >>> Ks.sort() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'dict_keys' object has no attribute 'sort' >>> Ks = list(Ks) >>> Ks.sort() >>> for k in Ks:print(k,D[k]) ... a 1 b 2 c 3 >>> D {'b': 2, 'c': 3, 'a': 1} #通過鍵視圖 >>> Ks = D.keys() >>> for k in sorted(Ks):print(k,D[k]) ... a 1 b 2 c 3 >>> D {'b': 2, 'c': 3, 'a': 1} #通過字典自身 >>> for k in sorted(D): print(k,D[k]) #或者直接sorted(D) ... a 1 b 2 c 3
字典內的函數
函數 | 描述 |
len(dict) | 返回字典元素個數,即鍵的總數。dict -- 要計算元素個數的字典。 |
str(dict) | 返回字符串,將值轉化為適於人閱讀的形式,以可打印的字符串表示。dict -- 字典。 |
type(dict) | 返回輸入的變量類型,如果變量是字典就返回字典類型。dict -- 字典。 |
dict.clear() | 沒有任何返回值。刪除字典內所有元素。 |
dict.copy() | 返回一個字典的淺復制。 |
dict.fromkeys(seq[, value])) | 創建一個新字典,以序列seq中元素做字典的鍵,value為字典所有鍵對應的初始值。seq -- 字典鍵值列表。value -- 可選參數, 設置鍵序列(seq)的值,默認為None。 |
dict.get(key, default=None) | 返回指定鍵的值,如果值不在字典中返回默認值None。key -- 字典中要查找的鍵。default -- 如果指定鍵的值不存在時,返回該默認值值。 |
dict.items() | 返回可遍歷的(鍵, 值) 元組數組。 |
dict.keys() | 返回一個字典所有的鍵。可迭代 |
dict.setdefault(key, default=None) | 和get()方法類似, 如果鍵不已經存在於字典中,將會添加鍵並將值設為默認值。key -- 查找的鍵值。default -- 鍵不存在時,設置的默認鍵值。 |
dict.update(dict2) | 把字典dict2的鍵/值對更新到dict里,dict2 -- 添加到指定字典dict里的字典。 |
dict.values() | 返回字典中的所有值。可迭代 |