Python 中不可变类型(整数)和可变类型(列表)的参数传递规则的理解

2 阅读2分钟

最近刷二叉树的问题 用了很多递归 那么我就发现了一个问题 对于在递归中数组发生改变的函数 我们通常要进行一次回溯 而对于在递归中整数 也就是整型变量发生改变的函数中却不需要 我感觉是有所不同的 但是为了确定我心中的想法进行了一系列资料的查询 最终得出了想要的答案

问题来源

让我产生问题的分别是112. 路径总和 513. 找树左下角的值 以及257. 二叉树的所有路径

路径总和
class Solution:
    def rest(self,node,summ):
        if not node:
            return
        summ=summ-node.val
        if summ==0 and (not node.left and not node.right):
            return True
        left=self.rest(node.left,summ)
        if left==True:
            return True
        right=self.rest(node.right,summ)
        if right==True:
            return True
        return False

    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        t=self.rest(root,targetSum)
        return t

这个是路径总和,变量summ每次都是同一个没有回溯

找树左下角的值
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root.left and not root.right:
            return root.val
        self.result=[]
        def depth(node,level):
            if not node:
                return
            if len(self.result)==level:
                self.result.append([])
            self.result[level].append(node.val)
            depth(node.left,level+1)
            depth(node.right,level+1)
        
        depth(root,0)
        return self.result[-1][0]

这里的level也没有在做什么改变

二叉树的所有路径
class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        def travel(node,result,Pass):
            Pass.append(node.val)
            if not node.left and not node.right:
                sPass="->".join(map(str,Pass))
                result.append(sPass)
            if node.left:
                travel(node.left,result,Pass)
                Pass.pop()
            if node.right:
                travel(node.right,result,Pass)
                Pass.pop()
            return
        if not root:
            return 
        Pass=[]
        result=[]
        travel(root,result,Pass)
        return(result)

先拆解一下这个函数吧,pass每次会储存节点,到达叶子节点后会加一个->变成spass 也就是一段路径 然后传到结果result当中,那么在这期间,每引用一次travel函数都会让pass增加一个数字,于是我们进行了一次回溯 确保在同一层中pass是相同的

解释和理解

在查阅资料后我发现了问题所在: 对于整型变量来说 比如调用t,每次调用t都只是在当前层中复制一个t的值然后传进去,每个递归调用都会创建独立的函数栈帧,栈帧里的remain_sum是局部变量,只在当前递归层级有效。左子树里的remain_sum修改,不会影响当前层,更不会影响传给右子树的remain_sum。 举个例子说明: 其实也就是说明了不可变类型的特点:就是修改时会创建一个新对象,而不是在原对象上修改,如同我们t=t-2一样,创建了一个新的t-2,然后把他赋给了一个变量t,而对于数组来说,我们修改数组(result.pop())就可以在原数组上发生,而不需要再重新赋值。