一、ChainMap
1、假如我们有两个字典,要查找某个关键字,我们必须同时检查这两个字典,比如先在x中查找,如果没有,再在y中查找。
x={'a':1,'c':2}
y={'b':3,'c':4}
我们可以使用ChainMap在逻辑上将多个字典合并成一个,以便同时执行某些操作。ChainMap可以接受多个字典,在逻辑上使他们表现为一个单独的映射结构。但是这些映射并不会真正的合并在一起。
from collections importChainMap
z=ChainMap(x,y)print(z)
ChainMap({'a': 1, 'c': 2}, {'b': 3, 'c': 4})
ChainMap只是维护了一个记录底层映射关系的列表,如果有重复的值,会采用第一个映射中对应的值,修改映射的操作总是会作用在第一个映射结构上。
print(z['a'])print(z['b'])print(z['c'])1
3
2 #这里z['c']的输出是第一个映射里的值
z['c']=10z['d']=20
print(z) #这里只修改了第一个映射里的c,只在第一个映射里添加了键值对:'d':20
ChainMap({'a': 1, 'c': 10, 'd': 20}, {'b': 3, 'c': 4})
del z['a'] #在z里删除关键字a,会在字典x中体现出来
print(x)
{'c': 10, 'd': 20}del z['b'] #通过z修改不了字典y
KeyError: "Key not found in the first mapping: 'b'"
使用ChainMap后,对原始映射的修改会反映到合并后的结果中
x={'a':1,'c':2}
y={'b':3,'c':4}
z=ChainMap(x,y)
x['a']=10
print(z)
ChainMap({'a': 10, 'c': 2}, {'b': 3, 'c': 4})
2、ChainMap和update的比较
对于字典的update方法,如果我们执行x.update(y),x会就地改变,如果y中有和x中一样的关键字,则y中关键字相应的值会覆盖x中相应关键字的值。
x={'a':1,'c':2}
y={'b':3,'c':4}
x.update(y)print(x)
{'a': 1, 'c': 4, 'b': 3}
二、defaultdict
1、如果我们想要一个一键多值字典,我们可以这样创建:
d={'a':[1,2,3],'b':[4,5,6]
}
e={'c':{1,2,3},'d':{4,5,6}
}
为了能方便的创建这样的字典,可以用collections中的defaultdict,defaultdict会自动初始化一个值。
from collections importdefaultdict
d=defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['a'].append(3)print(d)
defaultdict(list, {'a': [1, 2, 3]})
s=defaultdict(set)
s['a'].add(1)
s['a'].add(4)
s['b'].add(2)
s['b'].add(3)
s['c'].add(3)
s['c'].add(6)
s['c'].add(6)print(s)
defaultdict(set, {'a': {1, 4}, 'b': {2, 3}, 'c': {3, 6}})
2、defaultdict 和setdefault的比较
我们可以用setdefault来实现以上操作,但是每次到用setdefault都会创建一个初始值的新实例。
d={}
d.setdefault('a',[]).append(1)
d.setdefault('a',[]).append(2)
d.setdefault('b',[]).append(3)print(d)
{'a': [1, 2], 'b': [3]}
三、OrderedDict
控制字典中元素的顺序,可以使用collections模块中的OrderedDict类,当对字典做迭代时,它会严格按照元素初始添加的顺序进行。
from collections importOrderedDict
d=OrderedDict()
d['a']=1d['b']=2d['c']=3d['d']=4
for key ind:print(key,d[key])
a1b2c3d4
当想构建一个映射结构以便稍后对其做序列化或编码成另一种格式时,OrderedDict就很有用。
四、字典计算
prices={'acme':45.23,'aapl':612.78,'ibm':205.55,'hpq':37.20,'fb':10.75}
为了能对字典做一些有用的计算,通常会用zip()将字典的键和值反转过来。如下代码:
min_price=min(zip(prices.values(),prices.keys()))
max_price=max(zip(prices.values(),prices.keys()))print(min_price)print(max_price)
(10.75, 'fb')
(612.78, 'aapl')
prices_sorted=sorted(zip(prices.values(),prices.keys()))print(prices_sorted)
[(10.75, 'fb'), (37.2, 'hpq'), (45.23, 'acme'), (205.55, 'ibm'), (612.78, 'aapl')]
但是注意,zip()创建了一个迭代器,他的内容只能被消费一次。
prices_and_names=zip(prices.values(),prices.keys())print(min(prices_and_names))print(max(prices_and_names))
(10.75, 'fb')---------------------------------------------------------------------------ValueErrorValueError: max() argis an empty sequence
以上代码只输出了min,max并没有输出,迭代器的内容只能消费一次。
五、key视图和items视图的集合操作
字典的keys()方法返回keys视图对象,items()方法返回items视图对象,很少有人知道的是,他们直接支持常见的集合操作。但是values()返回的values视图并不能直接进行集合操作。
a={'x':1,'y':2,'z':3}
b={'m':4,'n':5,'x':1}print(a.keys()&b.keys())print(a.keys()-b.keys())print(a.items()&b.items())
{'x'}
{'z', 'y'}
{('x', 1)}