def classify(inputTree, featLabels, testVec):
"""
在实际数据集中改属性存储在哪个位置? 是第一个属性还是第二个属性?
:param inputTree:
:param featLabels:
:param testVec:
:return:
"""
firstStr = list(inputTree.keys())[0]
secondDict = inputTree[firstStr]
# 将标签字符串转换为索引, 使用index方法查找当前列表中第一个匹配firstStr变量的元素
featIndex = featLabels.index(firstStr)
for key in secondDict.keys():
# 比较testVec变量中的值与树节点的值
if testVec[featIndex] == key:
if type(secondDict[key]).__name__ == 'dict':
classLabel = classify(secondDict[key], featLabels, testVec)
else:
# 如果到达叶子节点,返回当前节点的分类标签
classLabel = secondDict[key]
return classLabel
关于递归函数多次调用return
第一次classLabel = classify(secondDict[key]), featLabels, testVec)调用了一次classLabel返回了classLabel 给了等号左边的classLabel,
第二次return classLabel给了主程序的调用处
首先你要理解函数调用的本质:
- 保存当前指令地址
- 跳转到被调用函数(指令段)的起始地址实际过程比这个复杂, 比如还包括保存临时变量和传参等等, 但是对我们正在讨论的问题不起到本质影响所以省略掉不谈
- 函数调用并不是在原地展开代码
- 每一个函数都是一段独立存在于存储器中的指令序列
- 每个程序的内存空间中都包括一个叫做"栈(stack)"的区域, 它的特点是先进后出, 就像一摞书, 只能往顶端放书, 也只能从顶端取书每当你调用一次函数, 就会向栈中压入(push)返回地址, 当函数返回(return)时从栈中弹出(pop)返回地址并跳转回返回地址.
- 所以, 自身调用乃至循环调用形成的递归调用在进行时, 就会不断压栈来保存函数运行状态, 当递归一层一层返回时, 则是不断出栈了函数调用并不是在原地展开代码