Python進階7——字典與集合

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》

 

歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章