1.創建字典的五種方式
d1=dict(one=1, two=2)
d2={'one':1, 'two':2}
d3=dict(zip(['one', 'two'], [1,2]))
d4=dict([('two', 2), ('one', 1)])
d5=dict({'one':1, 'two':2})
print(d1==d2==d3==d4==d5)
其中,四種是通過dict函數創建字典,d3中的zip函數的作用是將列表中的元素按照索引值對應打包成元組,並返回對應的迭代器
print(zip(['one', 'two'], [1,2]))
print(tuple(zip(['one', 'two'], [1,2])))
print(list(zip(['one', 'two'], [1,2])))
print(dict(zip(['one', 'two'], [1,2])))
2.字典解析式
字典解析式和列表解析式類似
nums=['one', 'two', 'three', 'four', 'five']
vals=[val for val in range(1,6)]
zipped=list(zip(nums, vals))
numlist={num:val for num, val in zipped}
print(numlist)
numlistpart={num:val for num, val in numlist.items() if val > 3}
print(numlistpart)
3.找不到key時,該怎麼做
上述的numlist中只存取了1到5的鍵值對,如果查找key爲six的值時,默認情況下,會拋出異常
print(numlist['five'])
print(numlist['six'])
如果不想拋出異常,可以使用dict中的成員函數setdefault來實現
numlist.setdefault('six', []).append('no six')
print(numlist['six'])
print(numlist)
setdefault函數返回的是一個空的列表,可以向列表中添加元素。執行完setdefault後,對應的key value被自動添加到字典中
除了setdefault成員函數,還可以使用defaultdict來避免keyerror異常
import collections as col#defaultdict在collections模塊中
nums=['one', 'two', 'three', 'four', 'five']
vals=[val for val in range(1,6)]
zipped=list(zip(nums, vals))#打包元素,返回元組列表
dd=col.defaultdict(list)#創建一個defaultdict,dd的value是列表
for k, v in zipped:
dd[k].append(v);#給dd賦值
print(dd)
print(dd['six'])#打印一個不存在的鍵,返回空列表
沒有出現keyerror,defaultdict中的參數表明了value值的類型,如果傳入的是其他類型,value的類型也發生變化
當把參數改爲int後的輸出結果如下:
4.特殊的魔術方法__missing__
字典訪問一個不存在的鍵並且不拋出異常的原因就是因爲魔術方法__missing__,當執行d[k]操作時,會調用__getitem__魔術方法,當找不到對應的key時,會調用魔術方法__missing__,在該方法中捕獲異常並返回默認值
舉例:定義一個能將字符串key轉爲int類型key的字典
class strkeydict(dict):
def __missing__(self, key):
print('__missing__')
if isinstance(key, int):#如果執行了__missing__並且key的類型是int,說明key不存在,拋出異常
raise KeyError(key)
return self[int(key)]#否則將其他類型的key轉爲int再次嘗試查找
def get(self, key, default=None):
print('get')
try:
return self[key]
except KeyError:
return default;
def __contains__(self, key):
print('__contains__')
return key in self.keys() or int(key) in self.keys()
strkd=strkeydict([(1,'one'), (2, 'two')])#因爲繼承
print(strkd)
print('-----------------------')
print(strkd['1'])#無法找到key爲'1'對應的值,調用__missing__,然後執行return self[int(key)]
print(strkd[1])#直接調用__getitem__
print('-----------------------')
print(2 in strkd)
print('1' in strkd)
print(3 in strkd)#strkd中無key爲3
print('-----------------------')
print(strkd.get(1))
print(strkd.get('2'))#無法找到key爲'2'對應的值,先調用__missing__,然後執行return self[int(key)]
print(strkd.get(3))#無法找到key爲3對應的值,觸發__missing__調用,拋出KeyError異常,然後由get函數捕獲異常,返回None
上述代碼和核心就是當執行self[k]的操作時,會調用__getitem__, 如果不成功,再繼續調用__missing__
此外__missing__中的isinstance判斷必不可少,如果沒有該判斷,會產生無限遞歸,因爲return self[int(key)]如果失效,會再一次調用__missing__,然後再return self[int(key)]
def __missing__(self, key):
print('__missing__')
# if isinstance(key, int):
# raise KeyError(key)
return self[int(key)]
print(strkd[3])
上述代碼還可以換一種寫法
import collections as col
class strkeydict1(col.UserDict):
def __missing__(self, key):
print('__missing__')
if isinstance(key, int):
raise KeyError(key)
return self[int(key)]
def __contains__(self, key):
print('__contains__')
return int(key) in self.data
def __setitem__(self, key, item):
print('__setitem__')
self.data[key]=item
def get(self, key, default=None):
print('get')
try:
return self[key]
except KeyError:
return default
strkd=strkeydict1([(1,'one'), (2, 'two')])
print(strkd)
print('-----------------------')
print(strkd['1'])
print(strkd[1])
print('-----------------------')
print(2 in strkd)
print('1' in strkd)
print(3 in strkd)
print('-----------------------')
print(strkd.get(1))
print(strkd.get('2'))
print(strkd.get(3))
print('-----------------------')
strkd[3]='three'
print(strkd)
主要的變化就是繼承了collections.UserDict,好處是可以直接訪問存儲字典實例的屬性data,簡化了__contains__的實現,也更方便的實現了__setitem__,核心思想仍然不變
5.字典視圖MappingProxyType
字典視圖MappingProxyType位於types模塊中,能夠動態的監視綁定字典的變化,只讀不可寫
import types as t
d=dict({1:'one',2:'two'})
dview=t.MappingProxyType(d)#綁定字典d,可以隨時查看d的數據
print(dview, d)
d[3]='three'
print(dview, d)
6.集合
集合的本質是一堆無重複的數據(也是用{}表示,只不過沒有鍵值對),所以可以用來去重(字典中重複的鍵值只會保留最後面的)
d=dict({1:'one',2:'two', 1:'six'})
s={1,1,2,3,4,5,5}
print(s,d)
交集,並集,補集
s1=set([x for x in range(0,6)])
s2=set([x for x in range(1,7)])
print(s1, s2)
print(s1&s2, s1|s2, s1-s2, s2-s1)
print(len(s1&s2))
&表示交集,|表示並集,用減號表示補集,求取交集之後,可以用len函數計算集合交集的個數。用來檢查某個集合在另一個集合中出現了多少次
由於&只能用於集合,如果想對兩個列表或元組求公共部分,需要先用set函數轉化爲集合,再使用&
l1=(x for x in range(0,6))
l2=(x for x in range(1,7))
print(set(l1)&set(l2))
空集合與空字典
集合與字典都用大括號{}表示,如果只寫了一個{},表示的是空字典而不是空集合
d={}
s=set()
print(type(d), type(s))
空集合用set()表示,空字典用{}表示
集合推導與字典推導和列表解析式類似
s={x for x in range(0,10)}
print(s)
參考:
《流暢的Python》
歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出