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])))

Python进阶7——字典与集合_第1张图片

 

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'])

Python进阶7——字典与集合_第2张图片

如果不想抛出异常,可以使用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

Python进阶7——字典与集合_第3张图片

上述代码和核心就是当执行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])

Python进阶7——字典与集合_第4张图片

 

上述代码还可以换一种写法

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)

Python进阶7——字典与集合_第5张图片

主要的变化就是继承了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》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

你可能感兴趣的:(Python进阶,python,列表,字典,集合)