Python类内调用View方法触发NameError: name 'view'未定义错误
问题现象
实现Python类完成二叉树底视图(bottomView)功能时,递归调用类内遍历方法触发NameError,原始代码如下:
class Solution: def bottomView(self, root): # code here v={0:root} self.View(root,v,0) return [ d for i,d in v.items()] def View(self,root,v,d): v[d]=root.data if root.left: view(self,root.left,v,d-1) if root.right: view(self,root.right,v,d+1)
运行抛出的错误栈:
Traceback (most recent call last): File "/home/f94469e221bb681a04f81ecf69c00640.py", line 103, in res = ob.bottomView(root) File "/home/f94469e221bb681a04f81ecf69c00640.py", line 7, in bottomView self.View(root,v,0) File "/home/f94469e221bb681a04f81ecf69c00640.py", line 12, in View view(self,root.left,v,d-1) NameError: name 'view' is not defined
错误根因
触发名称错误的核心原因有两个:
- 方法名大小写不匹配:Python对标识符大小写严格敏感,代码中定义的遍历方法是大写开头的
View,递归调用时写为小写开头的view,二者是完全独立的名称,解释器在当前作用域找不到view的定义就会抛错。 - 实例方法调用语法错误:类的实例方法不能直接通过方法名裸调用,必须绑定当前实例
self发起调用,调用时不需要手动传入self参数,该参数会被自动绑定。
除此之外原代码还有两处逻辑缺陷,会导致返回结果不符合底视图要求:
- 初始化字典时存入的是
root节点对象,后续遍历存入的是节点data属性,值类型不统一 - 直接遍历字典返回结果,没有按水平距离排序,输出顺序混乱,不符合视图从左到右的展示规则;且纯深度优先遍历不记录深度的话,同水平距离下可能出现上层节点覆盖下层节点的问题。
修复方案
推荐使用层序遍历(BFS)实现底视图,逻辑更直观,不会出现深度覆盖问题,修复后完整代码如下:
from collections import deque class Solution: def bottomView(self, root): if not root: return [] # 键为节点水平距离,值为对应节点值 dist_map = {} # 队列存储格式:(当前节点, 节点对应水平距离),根节点水平距离为0 q = deque([(root, 0)]) while q: node, cur_dist = q.popleft() # 同水平距离下,后遍历到的节点位置更靠下,直接覆盖旧值 dist_map[cur_dist] = node.data if node.left: q.append((node.left, cur_dist - 1)) if node.right: q.append((node.right, cur_dist + 1)) # 按水平距离从小到大排序,返回从左到右的底视图结果 return [dist_map[d] for d in sorted(dist_map.keys())]
如果要保留原有递归写法,需要补充深度校验,保证同水平距离下只保留最下层节点的值,递归版本修复代码如下:
class Solution: def bottomView(self, root): if not root: return [] # 键为节点水平距离,值为(节点深度, 节点值) dist_map = {} self.View(root, dist_map, 0, 0) return [dist_map[d][1] for d in sorted(dist_map.keys())] def View(self, root, dist_map, cur_dist, depth): # 同水平距离下,仅当当前节点深度大于等于已记录深度时更新值 if cur_dist not in dist_map or depth >= dist_map[cur_dist][0]: dist_map[cur_dist] = (depth, root.data) if root.left: # 正确调用实例方法:通过self调用,方法名大小写匹配,无需手动传self self.View(root.left, dist_map, cur_dist - 1, depth + 1) if root.right: self.View(root.right, dist_map, cur_dist + 1, depth + 1)
内容的提问来源于stack exchange,提问作者venkatesh Grandhi
相关产品推荐
相关产品推荐

