项目地址:https://github.com/mewwts/addict/blob/master/README.md
addict是一个Python模块,除了标准的项目语法外,还为您提供了字典,这些字典的值可以使用属性进行获取和设置。
这意味着您不再需要编写这样的字典:
body = {
'query':{
'filtered':{
'query':{
'match':{ 'description':'addictive' }
},
'filter':{
'term':{ 'created_by':'Mat' }
}
}
}
}
相反,您只需编写以下三行:
body = Dict()
body.query.filtered.query.match.description = 'addictive'
body.query.filtered.filter.term.created_by = 'Mats'
1、安装
支持python2.7、3.6和3.7,可以通过pip或conda安装:
pip install addict
conda install addict -c conda-forge
2、用法
addict继承自dict,但是在访问和设置其值方面更加灵活。现在,与词典一起工作是一件快乐的事!设置嵌套Dict的项是一个梦幻般的实现:
from addict import Dict
mapping = Dict()
mapping.a.b.c.d.e = 2
mapping
=>
{'a': {'b': {'c': {'d': {'e': 2}}}}}
如果Dict使用其它可迭代的值实例化,它将迭代并克隆这些值,并将dicts转换为Dicts。因此,可进行以下操作:
mapping = {'a': [{'b': 3}, {'b': 3}]}
dictionary = Dict(mapping)
dictionary.a[0].b
=>
3
但dictionary['a']已不是mapping['a']的引用了,两者的值互不影响。
mapping['a'] is dictionary['a']
=>
False
此行为仅限于构造函数,而不是在使用属性或项目语法设置项目时,不变引用:
a = Dict()
b = [1, 2, 3]
a.b = b
a.b is b
=>
True
3、要记住的东西-非字符串的键值设置/获取
请记住,int不是有效的属性名称,因此必须使用get- / setitem语法设置/获取非字符串的dict键。
addicted = Dict()
addicted.a.b.c.d.e = 2
addicted[2] = [1, 2, 3]
=>
{2: [1, 2, 3], 'a': {'b': {'c': {'d': {'e': 2}}}}}
但是,请随意混合使用以下两种语法:
>>> addicted.a.b['c'].d.e
2
4、属性关键字
如keys,items等属性。
addict不会让您覆盖dict的固有属性,因此以下操作无效:
mapping = Dict()
mapping.keys = 2
=>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "addict/addict.py", line 53, in __setattr__
raise AttributeError("'Dict' object attribute '%s' is read-only" % name)
AttributeError: 'Dict' object attribute 'keys' is read-only
但是,以下方式时是可以的:
>>> a = Dict()
>>> a['keys'] = 2
>>> a
{'keys': 2}
>>> a['keys']
2
就像普通的dict。对于可以使用的键,没有任何限制(除了常规命令所施加的限制)。
5、递归回退至dict
如果你觉得将addict运送到其他模块不安全,使用to_dict()方法,它会返回addic字典的常规dict副本。
regular_dict = my_addict.to_dict()
regular_dict.a = 2
=>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'a'
当您希望在几行中创建嵌套的Dict,然后将其发送到其他模块时,这是完美的选择。
body = Dict()
body.query.filtered.query.match.description = 'addictive'
body.query.filtered.filter.term.created_by = 'Mats'
third_party_module.search(query=body.to_dict())
6、计数器
Dict轻松访问和修改深层属性的能力使其非常适合计数。与相比collections.Counter,它具有明显的优势,因为它可以轻松实现多个级别的计数。
考虑以下数据:
data = [
{ 'born':1980,'gender':'M','eyes':'green' },
{ 'born':1980,'gender':'F','eyes':'green' },
{ 'born':1980,'gender':'M','eyes':'blue' },
{ 'born':1980,'gender':'M','eyes':'green' },
{ 'born':1980,'gender':'M','eyes':'green' },
{ 'born':1980,'gender':'F','eyes':'blue' },
{ 'born':1981,'gender':'M','eyes':'blue' },
{ 'born':1981,'gender':'F','eyes':'green' },
{ 'born':1981,'gender':'M','eyes':'blue' },
{ 'born':1981,'gender':'F','eyes':'blue' },
{ 'born':1981,'gender':'M','eyes':'green' },
{ 'born':1981,'gender':'F','eyes':'blue' }
]
如果您计算出相同born、gender、eyes的个数,则可以轻松计算以下信息:
counter = Dict()
for row in data:
born = row['born']
gender = row['gender']
eyes = row['eyes']
counter[born][gender][eyes] += 1
print(counter)
=>
{1980: {'M': {'blue': 1, 'green': 3}, 'F': {'blue': 1, 'green': 1}}, 1981: {'M': {'blue': 2, 'green': 1}, 'F': {'blue': 2, 'green': 1}}}
7、更新
addict为了方便起见,更改了更新功能dict。如果使用来更新嵌套项目,dict则会覆盖它:
d = {'a': {'b': 3}}
d.update({'a': {'c': 4}})
print(d)
=>
{'a': {'c': 4}}
addict会递归并实际更新嵌套的Dict。
D = Dict({'a': {'b': 3}})
D.update({'a': {'c': 4}})
print(D)
=>
{'a': {'b': 3, 'c': 4}}
什么时候特别有用?
当需要更新字典配置时,有则覆盖无则更新时使用addict更方便。