简述Orderdict,defaultdcit,ChainMap以及MappingProxyType
先说下功能以及该模块来之哪个包
Orderdict:有序字典,来至collections(好用)
defaultdcit:为确实的键添加默认的值,来至collections(感觉非常实用)
ChainMap:将多个字典映射到一个分组中,来至collections,(感觉有点鸡肋的功能)
MappingProxyType:将字典转化成只读新式,来至types,(有意思。)
先说Orderdict,前面实际操作中发现,除了字典生成式不能用,另外创建字典,获取信息,很多操作跟字典都是通用的。
我尽量找一些它特有的方式,给自己加深印象。
a = {'a': 2, 'b': 3, 'c': 4, 'd': 5, } o_d = OrderedDict() for k,v in a.items(): o_d[k] = v print(o_d) print(type(o_d)) print(o_d['a']) o_d['e'] = 5 o_d['d'] = 8 print(o_d)
OrderedDict([('a', 2), ('b', 3), ('c', 4), ('d', 5)]) <class 'collections.OrderedDict'> 2 OrderedDict([('a', 2), ('b', 3), ('c', 4), ('d', 8), ('e', 5)])
先生成了一个有序字典,看了下格式,有点像列表里面套元祖的形式,进行了一些常规操作,跟字典一样。
print(set(dir(o_d))-set(dir({}))) {'__reversed__', '__dict__', 'move_to_end'}
通过差集比较多了两个魔法方法,一个普通方法,吐血。。。。。
b = o_d.__reversed__() print(next(b)) print(list(b)) o_d.__dict__['x'] = 123 print(o_d) o_d.move_to_end('b') print(o_d) o_d.move_to_end('c',last=False) print(o_d) a,b = o_d.popitem() print(a,b) print(o_d) c,d = o_d.popitem(last=False) print(c,d) print(o_d)
e ['d', 'c', 'b', 'a'] OrderedDict([('a', 2), ('b', 3), ('c', 4), ('d', 8), ('e', 5)]) OrderedDict([('a', 2), ('c', 4), ('d', 8), ('e', 5), ('b', 3)]) OrderedDict([('c', 4), ('a', 2), ('d', 8), ('e', 5), ('b', 3)]) b 3 OrderedDict([('c', 4), ('a', 2), ('d', 8), ('e', 5)]) c 4 OrderedDict([('a', 2), ('d', 8), ('e', 5)])
通过实际操作发现,__reversed__有一点作用,可以把字典的key进行排序,然后返回一个迭代器。
__dict__没啥发现,感觉用不上,move_to_end可以通过输入key指定到最后,默认情况下,如果修改了last参数就到第一
popitem也一样,默认弹出最后一组,修改弹出第一个。
上次网上还看到一种比较帅气的取出有序字典的第一组数据。
print(next(iter(o_d.items()))) print(o_d)
('a', 2) OrderedDict([('a', 2), ('d', 8), ('e', 5)])
这样就可以不修改原来参数的情况下,获取第一个字典元素的数据。
下一个defaultdict,直接上代码:
from collections import defaultdict dd = defaultdict(list) dd['aa'].append(123) dd['bb'].append('') print(dd) dd2 = dict.fromkeys('1234',[]) print(dd2) dd2['1'].append(123) print(dd2)
defaultdict(<class 'list'>, {'aa': [123], 'bb': ['']}) {'1': [], '2': [], '3': [], '4': []} {'1': [123], '2': [123], '3': [123], '4': [123]}
通过对比发现defaultdict还是非常好用的,他会再你生成新的key时,按照你的要求,已经开辟了一个独立空间存放了value
对比了fromkeys,很早的时候我就用这个创建了一组字典,当时还想装逼,发现失败,这个生成后面的value如果是可变参数都指向同一个地址(不可变元素还时可以的)
关于defautdict其实更加准确的来说,跟setdefault对比更加合适,setdefault是对一个字典取值,有的话就取值,没的话就添加一个键值对进去。
其实defautdict,后面也可以通过=号的形式添加数据,如果读取到就返回数据,读取不到就把第一个参数执行变成value,key为取值的值,前面我填一个数据的时候,肯定每次取值都取不到,所以每次都给key生成一个list或[]的value
其实参数[]换成list函数也可以,因为执行list[],也是生成一个空列表。所以第一个参数确切的是返回一个函数。
from collections import defaultdict import time import random def choose(): return random.randint(10,20) dd = {'name': 'sidian', 'sex': 'male'} print(dd.setdefault('addr', 'hangzhou')) print(dd.setdefault('age', choose())) print(dd) def r_time(): return time.asctime() print('~' * 100) dd_default = defaultdict(r_time, hobby='watch_tv', **dd) # 返回函数,第二参数解包前面的字典参数,也可以用=号 print(dd_default['name']) # 取值 print(dd_default['hobby']) #取值 print(dd_default['time']) #没有就赋值 print(dd_default) print(dd_default['time']) '''这样测试来看,其实跟setdeault功能差不多,两者你想用哪个都可以。'''
hangzhou 18 {'name': 'sidian', 'sex': 'male', 'addr': 'hangzhou', 'age': 18} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sidian watch_tv Fri Nov 15 04:06:46 2019 defaultdict(<function r_time at 0x108b3c710>, {'hobby': 'watch_tv', 'name': 'sidian', 'sex': 'male', 'addr': 'hangzhou', 'age': 18, 'time': 'Fri Nov 15 04:06:46 2019'}) Fri Nov 15 04:06:46 2019
d_dict = defaultdict({'a':1, 'b':2}) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-538-495985ac56c1> in <module> ----> 1 d_dict = defaultdict({'a':1, 'b':2}) TypeError: first argument must be callable or None In [539]: d_dict = defaultdict(str,{'a':1, 'b':2}) In [540]: d_dict[12] Out[540]: '' In [541]: d_dict Out[541]: defaultdict(str, {'a': 1, 'b': 2, 12: ''})
再次使用,其实defaultdict第一个参数一定要是一个可调用参数,或者None,后面可以写一些普通的字典创建的语法。
读取这个对象时,有key就返回,没key就新建这个key位key,然后调用前面的函数,或者None,新建这组k,v,并返回这个函数的返回值或者None
同setdefault效果差不多,都是肯定有返回值的。底层都应该调用了__missing__。
ChainMap感觉挺鸡肋的函数,就是把两个字典合并了一下,可以找两个加起来的key,那直接uodate一下,返回一个新的扩展字典查找也不是一样吗?
d1 = {1: 2, 3: 4} d2 = {3: 4, 4: 5, 5: 6} d3 = ChainMap(d1,d2) print(d3,type(d3)) print(d3[3],d3[1])
ChainMap({1: 2, 3: 4}, {3: 4, 4: 5, 5: 6}) <class 'collections.ChainMap'> 4 2
MappingProxyType将返回一个收保护只读的字典,有意思。
from types import MappingProxyType d1 = {1: 2, 3: 4} d6 = MappingProxyType(d1) print(d6, type(d6), sep='===') d1[1] = 5 print(d1) d6[1] = 5 print(d6)
{1: 2, 3: 4}===<class 'mappingproxy'> {1: 5, 3: 4} Traceback (most recent call last): File "/Users/shijianzhong/Desktop/bit_coin/test_file/temp.py", line 65, in <module> d6[1] = 5 TypeError: 'mappingproxy' object does not support item assignment
2021年1月27日添加一个defaultdict格式化字段的用法,必须用%()s的格式化输出。
def constant_factory(value): return lambda: value d = defaultdict(constant_factory('<missing>')) d.update(name='John', action='ran') '%(name)s %(action)s to %(object)s' % d 'John ran to <missing>'
这个格式化输出确实写的很出色,到底是官方出品,口味非凡。