在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日