本文引用至: python基礎類型之dict&sethtml
在python中, 將數據結構分類了兩種,一種是序列(sequence), 另一種是字典(dictionary). 其中,序列也就是咱們前面所說的 list and tuple. 字典就是這裏將要說的兩種-- dict and set
前面介紹了,list && set. 這裏,咱們就來探討一下剩餘兩個datatypespython
dict 打個比方就至關於 js中的對象. 他實際就是一種散列表(hash)的形式. dict 中的內容是無序的, 但每個值都是以key/value形式出現, 因此當咱們須要查找值時, py會直接根據你調用的key來進行索引,最後返回你的值. 他的查找速度是極快的, 複雜度就是O(1)
而相應的損耗就是內存空間, 因此這也符合hash表的特徵, 速度快, 空間大. 經過時間換空間的方式,進行索引.
ok, 如今咱們來建立一個dict:web
>>> my_dict = {1: 'apple', 2: 'ball'} //key, 咱們也是能夠換的 >>> new_dict = {'name':'jimmy','age':18} // 訪問只能使用key >>> new_dict['age'] 18
實際上, dict就這麼簡單. 可是, 咱們須要理解他和list的不一樣, 因爲他的feature 是速度快, 空間大,便於查找. 因此這種方式也經常使用於, 數據存儲和傳輸那一塊.
那,有沒有什麼辦法能 convert dict to list呢?
absolutely.
直接使用 list方法便可json
>>> my_dict {1: 'apple', 2: 'ball'} >>> list(my_dict) [1, 2]
不過這樣的現實意義並不大, 由於,實際上,他只會截取你dict中的key 做爲list的value.
可是, list是不能直接轉換爲dict的, 除非你是結合元組進行使用.網絡
>>> my_dict = dict([(1,'apple'), (2,'ball')]) >>> my_dict {1: 'apple', 2: 'ball'}
最後咱們能夠總結一下就是:
數據結構
一樣無外乎就是CRUD。 這裏咱們慢慢講.app
這裏很容易理解, 即就是給dict添加新的內容. 不像, list中有關序列的append,extend,insert方法. 在dict中,只提供了setdefault(key[,value]),update([other]) 進行相關的添加操做.less
setdefault(key[,value]): 用來向dict中指定添加相應的序列. 若是不存在,則新增. 若是存在 則該次添加默認無效, 而且返回已經存在的值. 實際上,這個方法,真的頗有用. 當咱們須要判斷一個值是否存在,再添加時,就會用到該方法curl
>>> my_dict {1: 'apple', 2: 'ball'} >>> my_dict.setdefault(1,[2,3]) 'apple' //若是不存在則默認添加 >>> my_dict.setdefault(3,1) 1
update([other]): 該方法是用來批量加入dict。 other的類型能夠爲dict, 也能夠爲tuple+list. 咱們看一下官方給的答案:函數
D.update([E, ]**F) -> None. Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
上面那段話和keys方法扯上關係了. 實際上,keys是dict的方法. 因此就表明的着dict的類型. 若是你沒有keys 方法, 這裏就至關於使用for...in... 遍歷數據結構,而能這樣遍歷的, 就只有tuple+list. 看個demo:
>>> my_dict.update({1:2,3:4}) // 直接添加dict, 沒問題吧. 繼續 >>> my_dict.update([(5,1)])
就醬. 另外,提醒一點,除了setdefault方法之外的其餘方法,默認都會覆蓋原有的key/value pair.
這裏dict 提供了大概4種方法: pop,popitem,del, clear. 咱們分開來講一下:
pop(k[,d]): 要知道,dict 不一樣於dict 是沒有順序的. 若是你的pop不帶參數, 那就不能怪誰了, please go die. 全部pop的用法就是, 在dict中刪除指定的k, 另外你也能夠帶上,d(就是value). 若是dict中的k不存在的話, 該方法就會返回d, 不然直接返回刪除值.
//指定key刪除 >>> my_dict.pop('age') 27 // 因爲,ket->age已經被刪除了, 這裏咱們使用補充的value做爲備用,以防出錯. >>> my_dict.pop('age',12) 12 //直接返回實現設好的12
popitem(): 這個方法,就不用任何參數了, 他的做用就是,從你的dict中隨便刪除一個pair,並以tuple的形式返回. 但,若是dict已是empty, 那麼就 go die了.
>>> my_dict.popitem() ('name', 'Ranjit')
del : del 在這裏 就和list是同樣的了. 用來刪除指定的值.
>>> del my_dict['age']
clear(): 不說了, 就是清空的意思
在list中,咱們獲取部分元素 直接使用分片就行了, 或者大不了使用copy唄. 但在dict中就沒有這麼方便了.
因此, 爲了彌補這個defect, dict提供了幾個比較好的方法.
有: fromkeys(seq[, v]),get(key[,d]),copy(),items(),keys(),values()
莫急,咱們慢慢看
fromkeys(seq[, v]): 該方法,實際上就是提取公因式, 用來給不一樣的keys 使用同一個val. 生成一個新的dict. 因此,這也引出了下文會提到的comprehension.
>>> dic = dict.fromkeys([1,2,3],12)
get(key[,d]): 相比,直接經過dict[xx]訪問方式而言, 我以爲這個方法,真的沒有什麼用. 比較好的也是他的一個判斷, 當key不存在值,他不會報錯,而且若是你設置好了d,那麼不存在的話,就會返回d.
>>> my_dict.get('name') 'Ranjit' // 不存在jimmy的key >>> my_dict.get('jimmy','sexy') 'sexy'
copy(): 不說了, 就是所有複製
items(): 用來返回,dict_items的類型. 他的形式就至關於tupe+list
>>> my_dict.items() dict_items([('name', 'Ranjit'), ('address', 'Downtown')])
只是他的類是dict_items
>>> type(my_dict.items()) <class 'dict_items'>
keys(): 以dict_keys的形式返回dict中的鍵值.
>>>my_dict.keys() dict_keys(['name', 'address'])
values(): 一樣, 以dict__values的形式,返回value值.
>>> my_dict.values() dict_values(['Ranjit', 'Downtown'])
最後,說一下最後3種類型, dict_items,dict_keys,dict_values. 到底幹嗎的.
官方解釋是, 這些至關於只是一個快照(view). 並不會持續存在,這樣作的目的就是爲了節省內容. 並且,若是你想將兩個 dict進行比較的時候, 實際上,只要比較他的dict.values,dict.keys 或者, dict.items 是否相同便可. 由於,這樣比較快.(不過,因爲無序,你也能夠直接比較)
>>> dic.items() == my_dict.items() True
另外,若是你想講keys或者values保留下來,能夠直接使用list方法進行轉義便可.
>>> list(dic.values()) ['jimmy', 'Downtown']
最後再補充一下關於dict的 周邊方法.
這個和list類型,用來迅速生成一個dict
>>> squares = {x: x*x for x in range(6)} >>> squares {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
只要後面是一個能夠遍歷的數據結構就行.
另外, 使用for...in... 遍歷dict, 他的結果是遍歷當中的key 而不是, value.
>>> for x in squares: ... print(x)
dict 在python中叫作字典, 而在js中 叫作對象. 將對象字符串化, 就是JSON的實質.
實際上, 這種格式,是很是利於網絡傳輸的. 如今, 大部分web傳輸方式都是使用JSON (JavaScript Object Notation)格式, 而上面的書寫方式, 只須要轉爲json便可。
py 提供了咱們一個json的模塊, 裏面有一些基本方法,最經常使用的,要算dumps和loads.
作個類比:
dumps: 至關於js中的JSON.stringify()
loads: 至關於js中的JSON.parse()
來具體看看方法參數吧:
loads(s, encoding=None[,...]): 實踐上,這是loads提供的參數配置, 通常而言, 咱們只須要默認參數便可. 使用方法很簡單:
>>> json_str '{"shares": 100, "name": "ACME", "price": 542.23}' >>> json.loads(json_str) {'name': 'ACME', 'shares': 100, 'price': 542.23}
對比一下,引號應該就知道其中的意義了.
dumps(obj[,..]): 一樣,dumps 咱們使用默認參數便可. 用來將obj 轉化爲str.
>>> data {'shares': 100, 'name': 'ACME', 'price': 542.23} >>> json.dumps(data) '{"shares": 100, "name": "ACME", "price": 542.23}'
一樣,你們比較一下就知道了.
另外, 這裏須要說起幾點的是: 在和JSON相互轉化的過程當中, FalseTrue converted to false/true. None -> null. 另外json 中還提供了 load,dump方法,用來對文件進行操做. 有興趣的同窗,能夠參考一下官方文檔: json
來看張總結圖譜吧
這裏,想要介紹一個, 專門爲數學運算準備的數據結構--set. set不一樣於dict, 他沒有成對的key/value。 他只會包含,不重複的value. 一個簡單的set,咱們能夠這麼寫
>>> s = {1,2,3,4} // 若是你要建立空的set的話, 請使用set()方法. >>> s = set() // 否則的話, 就是dict類型了
就是講你所須要的值放在 curly braces裏面便可.
咱們來看看他最重要的feature--不重複
>>> s = {x for x in [1,1,1,1]} >>> s {1}
另外, set是不能包含mutable datatype. 好比 list。(tuple 能夠)
>>> s = {[1,2,3]} TypeError: unhashable type: 'list' // 已經給出, 不能存放非 hash 值
實際上, set還有一個很重要的做用,就是用來 remove duplicates. 特別針對於list
使用方法就是直接使用set()進行過濾便可. 咱們能夠定義一個函數unique
def unique(l): l = set(l) l = list(l) return l >>> unique([1,1,1]) [1]
那麼,咱們怎麼訪問set呢?
孩紙, 對不起,
一樣, set和dict類型, 也存在CRUD操做, 不過,他還自帶了innate buffer. 集合運算
py提供了兩個方法, 一個是add, 一個是update.
add(ele): 該方法,用來添加一個ele. 但若是該ele存在, 那麼該次添加就是useless
>>> new_set {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> new_set.add(10)
update(iterable): 該方法用來添加多個set元素. 參數必須是能夠遍歷的.好比,list,set,tuple,dict. 固然,若是是dict的話, 他只會添加key進去
>>> new_set.update({'a':1,'b':2}) {'a','b'}
在set中, 一樣提供了幾個可供處理的方法: discard,remove,pop,clear.
discard(ele)和remove(ele) 其實是有點相像的. 惟一的difference是, 使用discard時, 若是元素不存在,不會報錯,而remove會.
>>> my_set {1, 3, 5} >>> my_set.discard(2) >>> my_set {1, 3, 5} >>> my_set.remove(2) KeyError: 2
那set不是無序的嗎? 爲何會有pop這個方法呢?
對比與dict 中的popitem方法而言, 在set中,pop就已經能夠表明這個意思了. 即, 使用pop()方法,會隨機刪除 set中的某一個值.而且會返回刪除的值. 若是爲空的話,會報錯
>>> new_set {0, 1, 2} >>> new_set.pop() 0
clear就是清空的意思,就醬.
對於list有tuple, 而set 對應的immutable datatype就是 frozenset. frozenset實際上就是 固定的set. 因此, 對於create 和 delete 方法而言是不能應用在frozenset上的. 那frozenset該怎麼玩呢?
定義一個frozenset, 能夠直接使用frozenset() 方法.
frozenset(iterable): 它裏面接受能夠進行遍歷的datatype, 上面所說的 set,list等都行
>>> A = frozenset([1, 2, 3, 4]) >>> A frozenset({1, 2, 3, 4})
那咱們何時會使用到呢?
表問我, 我也母雞. 看心情吧
接下來,才應該是set的重頭戲, 集合操做.
簡單的結合操做無外乎: 交(&),並(|),差(-),對稱差(^). 簡單的還有包含(⊆),真包含(⊂).
咱們先來看幾個容易理解的:
兩個集合相併:
在python中, 咱們可使用|
operator。 或者是union()方法
>>> A | B {1, 2, 3} >>> A.union(B) //等價於 >>> B.union(A)
還記得, 並的對稱性吧. A|B = B|A
兩個集合相交:
在python中, 咱們就可使用 &
表達式, 或者 intersection方法,來作.
>>> A & B {4, 5} >>> A.intersection(B) {4, 5} >>> B.intersection(A) {4, 5}
兩個集合的差集:
在python中, 咱們就可使用-
或者difference()方法來表示
>>> A - B {1, 2, 3} >>> A.difference(B) {1, 2, 3}
這個就是上圖的表達式
兩個集合的對稱差 [(A-B)∪(B-A)]:
在python中,表達可使用^
或者symmetric_difference()方法.(你以爲那個簡單?)
>>> A ^ B {1, 2, 3, 6} >>> A.symmetric_difference(B)
上面兩個就是兩個集合的基本操做. 而且衍生出另一個set. 在python的set操做中, 還有判斷兩個集合是否相關的方法: isdisjoint(),issubset(),issuperset().
如今假設有集合A和集合B。
>>> B {0, 1, 2, 3} >>> A {0, 1, 2}
isdisjoint(): 判斷兩集合是否相交. 記住, 包含並非相交, 相交是指有一部分包括,有一部分不包括, 至關於就是兩個圓外邊界相交
>>> A.isdisjoint(B) //兩個的關係是包含的意思 False >>> A.issubset(B) True
A.issubset(B): 判斷集合B是否包含集合A. 固然, 徹底相等也算包含. 實際上就是數學中的⊆.
A.issuperset(B): 判斷集合A是否包含集合B。 這裏我就不繞了, 你們看狀況使用便可.
>>> A.issubset(B) True >>> A.issuperset(B) False
另外, 咱們檢查一個元素是否在另一個set中,能夠直接使用 in
關鍵字了.
看個demo.
>>> A {0, 1, 2, 3} >>> 1 in A True
到這裏, set的基本內容,應該差很少了. 剩下的就是在實踐中,不斷磨練了.
看個總結圖: