Python中用点运算符操作字典的方法

在Python编程中,有时候我们会将数据保存在字典中。一般情况下,我们会通过键值来访问字典中的数据,比如说:

a = {'key1': 1, 'key2: 2}
print(a['key1'])

有些时候字典发生了嵌套,那么会以如下形式访问字典中的数据:

a = {'key1': 1, 'key2': {'key21': 21, 'key22': {'key221': 221, 'key222': 222}}}
print(a['key2']['key22']['key222'])

这么多方括号,简直看上去又烦人,又愚蠢。

我写代码喜欢用VS Code,并且仅仅是作为编辑器,不装任何Python插件,因此也无法实现比较智能的补全。不过我没记错的话,一般的IDE似乎也没法补全以字符串为主的键值,这样子写代码就很烦,容易写着写着就去神游了。

因此就在想,是不是可以用点运算符,类似于访问类成员变量、成员函数那种形式去访问字典里边的数据呢。

然后我就发现了一个官方类,叫做SimpleNamespace,它在types包里边。可以完美实现咱们的需求。

from types import SimpleNamespace
a = {'key1': 1, 'key2: 2}
b = SimpleNamespace(**a)

此时我们打印b变量,可以看到:

namespace(key1=1, key2=2)

此时可以用点运算符访问。也能够新增值和删除值。

print(b.key1)
print(b.key2)
b.key3 = 3
del b.key2

同样的,我们也可以把已经转换为SimpleNamespace类型的字典转换回来。

c = vars(b)

那么如果有字典嵌套的情况下,怎么互相转换呢?显然我们不能一层一层手动转换。

我们可以写两个函数完成操作。

from types import SimpleNamespace

def dict_to_ns(_dict):
    for key in _dict.keys():
        if isinstance(_dict[key], dict):
            _dict[key] = dict_to_ns(_dict[key])
    _dict = SimpleNamespace(**_dict)
    return _dict

def ns_to_dict(_ns):
    _dict = vars(_ns)
    for key in _dict.keys():
        if isinstance(_dict[key], SimpleNamespace):
            _dict[key] = ns_to_dict(_dict[key])
    return _dict

然后我们可以将上边那个复杂的嵌套字典进行一下转换:

a = {'key1': 1, 'key2': {'key21': 21, 'key22': {'key221': 221, 'key222': 222}}}
b = dict_to_ns(a)

我们将b变量打印出来,可以看到:

namespace(key1=1, key2=namespace(key21=21, key22=namespace(key221=221, key222=222)))

然后我们可以用点运算符访问了。

print(b.key2.key22.key222)

这个样子是不是舒服很多?而且VS Code还能自动补全,写代码体验瞬间增强了好多。

Yannx

2020年6月26日

Leave a Comment