Python创建dict-keys路径类似于mkdir-p



假设我们有一个从json解析的dict,并以密钥路径path-to.my.keys的形式从密钥中读取值

my_dict['path-to']['my']['keys']

在文件系统中,如果mkdir -p不存在,则它可以创建这样的路径。

在python中,我们是否有类似的语法/函数来为dict创建key path,也就是为缺少键的默认空dict?我的谷歌搜索结果没有太大帮助。

TLDR

您可以使用dict.setdefaultcollections.defaultdict

def make_path(d: dict, *paths: str) -> None:
for key in paths:
d = d.setdefault(key, {})
make_path(my_dict, 'path-to', 'my', 'keys')
assert my_dict['path-to']['my']['keys'] is not None

完整详细信息

解决方案1。dict.setdefault

my_dict.setdefault('path-to', {}).setdefault('my', {}).setdefault('keys', {})

优点:

  • my_dict为正常dict
  • 使dict只显式发生
  • 深度无限制

缺点:

  • 您应该在每个用例中调用setdefault方法

解决方案2。collections.defaultdict

from collections import defaultdict
my_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
my_dict['path-to']['my']['keys']

优点:

  • 您根本不需要调用来检查是否存在

缺点:

  • 制作字典是隐含的
  • CCD_ 11不是纯CCD_
  • 根据my_dict的定义,您有深度限制

解决方案3。解决方案1的高级功能:制作自己的功能

def make_path(my_dict: dict, *paths: str) -> dict:
while paths:
key, *paths = paths
my_dict = my_dict.setdefault(key, {})
return my_dict

test = {'path-to': {'test': 1}}
print(test)
make_path(test, 'path-to', 'my', 'keys')['test2'] = 4
print(test)
print(make_path(test))  # It's okay even no paths passed

输出:

{'path-to': {'test': 1}}
{'path-to': {'test': 1, 'my': {'keys': {'test2': 4}}}}
{'path-to': {'test': 1, 'my': {'keys': {'test2': 4}}}}

解决方案4。来自解决方案2的高级:创建自己的类

class MyDefaultDict(dict):
def __missing__(self, key):
self[key] = MyDefaultDict()
return self[key]

my_dict = MyDefaultDict()
print(my_dict)
my_dict['path-to']['my']['keys'] = 'hello'
print(my_dict)

输出:

{}
{'path-to': {'my': {'keys': 'hello'}}}

结论

我认为解决方案3最符合您的需求,但如果适合您的情况,您可以使用任何其他选项。


附加

在解决方案4中,我们已经从json中解析了dict:d,怎么样?您的解决方案从MyDefaultDict((类型开始,而不是从jsons.loads((返回的类型开始

如果您可以编辑json.loads部分,请尝试:

import json

class MyDefaultDict(dict):
def __missing__(self, key):
self[key] = MyDefaultDict()
return self[key]

data = '{"path-to": {"my": {"keys": "hello"}}}'
my_dict = json.loads(data, object_pairs_hook=MyDefaultDict)
print(type(my_dict))

输出:

<class '__main__.MyDefaultDict'>

有一个递归defaultdict技巧,允许您在嵌套结构的随机路径上设置值,而无需显式创建路径:

import json
from collections import defaultdict
nested = lambda: defaultdict(nested)
d = nested()
d['path']['to']['nested']['key'] = 'value'
print(json.dumps(d))
# {"path": {"to": {"nested": {"key": "value"}}}}

不存在的键将返回空的defaultdict。

在python中,我们是否有类似的语法/函数来为dict创建密钥路径?我的谷歌搜索结果没有太大帮助。

Python没有clojure&没有。不过,为了方便使用setdefault方法,它可以在运行时以一定的成本处理这种特定情况:dict.setdefault(key, default)将在设置键后返回该键的值,如果它丢失,则my_dict.setdefault('path-to', {}).setdefault('my', {}).setdefault('keys', ???)将访问指定的路径,在它们丢失的地方设置dict。

回答您的问题--是。

在python中,您可以使用subprocess模块来执行您通常在系统上执行的所有命令。

您可以从python中执行相同的mkdir -p命令来创建嵌套目录usinfsubprocess.Popen

以下是如何做到这一点:

import subprocess
# Create a string of nested directory path.
path_from_dict_keys = "dir1/dir2/dir3"
temp = subprocess.Popen(['mkdir', '-p', path_from_dict_keys], stdout = subprocess.PIPE) 
# we use the communicate function to fetch the output 
output = str(temp.communicate())

最新更新