一、问题起因
为什么会使用到递归,是在做接口自动化的时候,我把yaml文件作为数据配置的存储,例如:账号、密码、地址等
自动化项目中的数据分离
我读取到的yaml是一个字典,每次都要按照从最外层级来开始定位获取值,如果我嵌套了好几层的话,写起来也比较麻烦,我就想如果我能方便的找到任意一个层级的key-value就好了。
于是接触到了递归。
二、递归原理
简单的来讲:一个函数在内部调用自身本身,这个函数就是递归函数。
2.1关于递归的一种解释:
此解释来源
我们使用的词典,本身就是递归,为了解释一个词,需要使用更多的词。当你查一个词,发现这个词的解释中某个词仍然不懂,于是你开始查这第二个词,可惜,第二个词里仍然有不懂的词,于是查第三个词,这样查下去,直到有一个词的解释是你完全能看懂的,那么递归走到了尽头,然后你开始后退,逐个明白之前查过的每一个词,最终,你明白了最开始那个词的意思。。。
三、递归需要注意的地方
3.1递归函数的理解:
来源:递归详解
https://www.cnblogs.com/Fantinai/p/7806356.html
在这里我理解的是,当调用递归的时候,进入更深的下一层,但是上一层并没有结束,而是在等待下一层的方法结束。
这让我想起了剥洋葱,一层一层的剥洋葱,每一层洋葱就是我们的这个方法,一层层的洋葱就是一层层的递归,每剥一层我们的洋葱(递归的数据)就会小一些,直到找到最里面的芯,这个时候递归结束,然后再把一层层的洋葱套回去。
3.2递归的返回(return)值:
还拿我上面说的洋葱来举例吧,如果我需要获取洋葱芯的值,那就需要把洋葱芯一层层的返回(return)到上一层,然后上一层再给上上一层,直到传递到最外层我才能获取到这个洋葱芯。
我在写获取多层字典的方法时(示例见下面的代码),在调用递归,也就是自身方法后,没有将值return回去,所以写的方法总是返回None。
也就是说,我在最深层找到值后,return传递到了倒数第二层,这个时候倒数第二层的函数是没有找到key值的,但是它已经从倒数第一层获取到了返回值,所以应该继续往上传递这个参数,也就是把调用递归函数获取到的值return出来。
我的思路:
递归方法(查找的key值, 一个字典):
for循环所有这一层的key值:
如果:key值是我想要查找的
return key对应的value
否则:如果当前key值的value是字典
调用递归方法(查找的key值, 当前的key的value值):
# 这个地方也要return返回:调用递归所获取到的值
3.3递归的深度限制:
递归的深度也是有限制的,这是由于递归在调用自身时,过多的递归会导致栈溢出,默认的递归深度是:998层。不过在我需要查找的配置文件里,绝对是用不到这么深的层级的,所以目前不用担心这个问题。
四、写一个递归获取多层字典的方法
最终通过传递字典和key值,获取到key在多层字典中值的方法:
def get_any_key_info(key_name="", yaml_data=None):
# for循环字典这一层的所有key值
for i in list(yaml_data.keys()):
# 如果当前的key是我们要找的
if i == key_name:
return yaml_data[i]
# 如果当前的key不是我们找的key,并且是字典类型
elif type(yaml_data[i]) == dict:
# 使用递归方法,查找下一层的字典
recursion = get_any_key_info(key_name, yaml_data[i])
# 每层递归要返回一个值,否则函数默认返回None
return recursion
yaml = {"host": "灰度环境",
"平台一账号": {"user1": "二狗", "user2": "大黑"},
"平台二账号": {"user3": "金苹果", "user4": "root"}}
value = get_any_key_info("user1", yaml)
print(value)