python addict模块-像类对象一样优雅的访问字典

项目地址: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更方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jingbo1801

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值