树结构遍历递归失效:节点文档单词出现次数统计报错
解决递归失败与TypeError问题的方案
首先,你的代码里有几个关键问题导致了报错和递归不触发,我来逐个拆解并修正:
1. 核心错误:函数名被字典覆盖引发TypeError
你在循环子节点时,把递归函数名occurlist赋值成了空字典:
occurlist = {}
这就导致后续尝试调用occurlist(nn)时,实际是在调用一个字典对象而非原函数,自然会抛出TypeError: 'dict' object is not callable。解决方法很简单——把这个字典变量改名,比如叫current_occurlist,避免和函数名冲突。
2. 递归触发条件完全无效
原代码里的if not nn.update:完全没有意义:nn是你的节点对象,update是字典的内置方法,节点根本没有这个属性,这个判断永远不会成立,递归自然不会执行。你需要直接去掉这个错误判断,对每个子节点调用递归函数即可。
3. 逻辑混乱:每个节点的occurlist应基于自身文档集合
你的需求是每个节点统计自身文档中每个单词出现的文档数量,不需要把子节点的文档混入当前节点的统计逻辑。每个节点应该独立处理自己的documents属性,再递归处理子节点。
修正后的完整代码
import itertools import copy def calculate_occurlist(node): # 处理当前节点的occurlist:统计自身文档中每个单词的出现文档数 if not node.documents: node.occurlist = {} return # 获取当前节点所有文档中的单词集合(去重) all_words = set(itertools.chain.from_iterable(node.documents)) # 初始化统计字典 occur_dict = {word: 0 for word in all_words} # 遍历每个文档,统计单词出现的文档数 for doc in node.documents: doc_word_set = set(doc) for word in all_words: if word in doc_word_set: occur_dict[word] += 1 node.occurlist = occur_dict print(f"已处理节点 {node.name},生成occurlist") # 递归处理所有子节点 for child in node.children: calculate_occurlist(child) # 从根节点启动递归 calculate_occurlist(Savings_Accounts)
代码说明
- 函数名改为
calculate_occurlist,彻底避免和内部变量名冲突(你也可以保留原函数名,只要内部变量不重名即可) - 先处理当前节点:
- 提取所有单词的集合,避免重复统计
- 用集合判断单词是否在文档中(比直接
word in doc效率更高,尤其适合长文档) - 统计每个单词出现在多少个文档中,赋值给节点的
occurlist
- 递归处理子节点:直接遍历
node.children,对每个子节点调用递归函数,确保所有层级的节点都被处理
测试验证
用你给出的示例测试:
# 模拟节点类 class Node: def __init__(self, name, documents, children=None): self.name = name self.documents = documents self.children = children or [] self.occurlist = {} # 创建示例节点A A = Node("A", [['b','m','n'],['b'],['g'],['o','b','g'],['b','g']]) calculate_occurlist(A) print(A.occurlist) # 输出:{'b':4, 'm':1, 'n':1, 'g':3, 'o':1},完全符合预期
这样修改后,递归会正常触发,每个节点的occurlist都会正确生成,也不会再出现类型错误。
内容的提问来源于stack exchange,提问作者Ankita Patnaik
相关产品推荐
相关产品推荐

