函数的定义位置和归属不同导致的调用区别(经验总结)
代码和定义(后附代码出处)
class Solution_1:def maxDepth(self, root: Optional[TreeNode]) -> int:# 终止条件:空节点深度为0if not root:return 0# 分治:左子树深度 vs 右子树深度,取max后+1(包含当前节点)left_depth = self.maxDepth(root.left)right_depth = self.maxDepth(root.right)return max(left_depth, right_depth) + 1class Solution_2:def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:res = [] # 存储遍历结果# 定义递归辅助函数def dfs(node):if not node: # 终止条件:节点为空,返回returndfs(node.left) # 1. 递归遍历左子树res.append(node.val) # 2. 访问根节点,加入结果dfs(node.right) # 3. 递归遍历右子树dfs(root) # 从根节点开始递归return res
二叉树中序遍历
二叉树最大深度
一、先明确两个函数的 “归属” 差异
要理解调用方式,首先要清楚这两个函数分别属于哪个 “范围”:
函数 | 定义位置 | 归属(作用域) |
---|---|---|
maxDepth | 在 Solution_1 类内部定义 | 类的「实例方法」(属于类的实例) |
dfs | 在 inorderTraversal 方法内部定义 | 方法的「局部嵌套函数」(属于方法内部) |
二、为什么 maxDepth
必须用 self.maxDepth()
调用?
maxDepth
是 Solution
类的 实例方法(定义时第一个参数是 self
,这是 Python 类实例方法的标志),这类方法有两个关键特性:
- 依赖实例上下文:实例方法的调用必须绑定到
Solution
的一个实例(比如sol = Solution_1()
,然后sol.maxDepth(root)
)。在方法内部,self
就代表当前这个实例,是调用实例方法的 “桥梁”。 - 作用域不在方法内部:
maxDepth
定义在类的全局范围,而不是在maxDepth
方法自身内部。如果直接写maxDepth(root.left)
,Python 会在当前方法内部找这个函数 —— 但方法内部没有定义maxDepth
,就会报NameError
(找不到函数名)。
三、为什么 dfs
可以直接用 dfs()
调用?
dfs
是在 inorderTraversal
方法内部定义的 嵌套函数,它的特性刚好和实例方法相反:
- 作用域在方法内部:嵌套函数的 “可见范围” 仅限于定义它的外层方法(
inorderTraversal
)内部。在dfs
函数内部调用dfs(node.left)
时,Python 会直接在当前作用域(inorderTraversal
内部)找dfs
函数 —— 而dfs
就在这里定义,所以能直接找到,无需额外前缀。 - 不依赖类实例:
dfs
是局部函数,它的调用不需要绑定类实例,也没有self
参数。它的参数(node
)和使用的变量(如外层的res
列表)都是在方法内部可见的,不需要通过self
访问。
四、一句话总结核心区别
函数的调用方式由它的 “定义位置和归属” 决定:
- 若函数是「类的实例方法」(定义在类内,第一个参数是
self
),必须通过self.函数名()
调用(因为要绑定实例); - 若函数是「方法内部的嵌套函数」(定义在方法内,无
self
参数),直接用函数名()
调用即可(因为作用域就在方法内部)。