简述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>'

  这个格式化输出确实写的很出色,到底是官方出品,口味非凡。

 

posted @ 2019-11-13 01:44  就是想学习  阅读(671)  评论(0编辑  收藏  举报