假设:有深度不确定的字典,如何从中取出任一key的值?
方案:类似ansible资产文件的yml格式的处理方式
假定yaml内容如下:
handler:
users:
user01: 1.1.1.1 #冒号和-后面的空格是必须的
user02: 2.2.2.2
book:
book01: 3.3.3.3
book02: 4.4.4.4
nginx01: 5.5.5.5
tomcat01: 6.6.6.6
解析出来的字典为(即为开头所说的不定深字典)
{'handler': {'users': {'user01': '1.1.1.1', 'user02': '2.2.2.2'}, 'book': {'book01': '3.3.3.3', 'book02': '4.4.4.4'}}, 'nginx01': '5.5.5.5', 'tomcat01': '6.6.6.6'}
思路:利用递归思想
函数:
def get_keys(keys, dic=None, ret=None):
"""
从长度和结构层次未知的字典对象中取出指定key的值(若key的值为字典,则递归展示其最小粒度的键值对)
keys: 可迭代容器,元素为要获取值的键
dic: 字典对象
ret: 一个上层空列表,用来存储递归获得的信息
"""
for key in keys:
if key in dic:
if isinstance(dic[key], dict):
get_keys(dic[key].keys(), dic=dic[key], ret=ret)
else:
ret.append((key,dic[key]))
else:
for inner in dic:
if isinstance(dic[inner], dict):
get_keys([key], dic=dic[inner], ret=ret)
验证:
这个版本的下面几种情况已ok,目测已经覆盖了所有场景
get_target(['handler'],conf_dict=d)
get_target(['users'],conf_dict=d)
get_target(['tomcat01'],conf_dict=d)
get_target(['tomcat01','nginx01'],conf_dict=d)
get_target(['nginx01','user'],conf_dict=d)
get_target(['users','tomcat01'],conf_dict=d)
get_target(['nginx01','handler','tomcat01'],conf_dict=d)
get_target(['book','users'],conf_dict=d)
手写递归过程