You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何replaceNode1可正常运行而replaceNode2不行?Python变量赋值疑问

为什么replaceNode1函数能正常运行,replaceNode2却不行?

先看你给出的代码片段:

class Node: 
    def __init__(self, val): 
        self.val = val 
        self.left = None 
        self.right = None 

def replaceNode1(): 
    node = [None] 
    def doit(val, node): 
        node[0] = Node(val) 
    doit(20, node) 
    return node[0].val # 返回20 

def replaceNode2(): 
    node = None 
    def doit(val, node): 
        node = Node(val) 
    doit(20, node) 
    return node.val # 报错:'NoneType' has no attribute 'val'

核心原因在于Python的参数传递规则,以及可变对象和不可变对象的区别——你提到None是可变的?不对哦,None其实是不可变对象,而且这里的关键不是对象本身的可变性,而是函数内部对参数的操作方式。

我给你拆解一下两个函数的运行逻辑:

先看replaceNode1的运行过程

  1. 外层函数里node = [None],这里的node是一个列表(可变对象),它就像一个装着None的盒子,变量node只是贴在这个盒子上的标签。
  2. 调用doit(20, node)时,把这个盒子的标签复制了一份传给doit里的参数node——现在内外两个node标签都贴在同一个盒子上。
  3. doit里执行node[0] = Node(val),这是修改盒子内部的内容:把盒子里原来的None换成了新的Node实例。
  4. 回到外层函数,原来的node标签还是贴在那个盒子上,自然能拿到修改后的内容,所以返回20没问题。

再看replaceNode2的问题所在

  1. 外层函数里node = None,这里的node标签贴在了None这个不可变对象上(你可以把None理解成一个不能被修改的空盒子)。
  2. 调用doit(20, node)时,同样复制了一份标签传给doit的参数node——现在内外两个node标签都贴在None这个空盒子上。
  3. doit里执行node = Node(val),这不是修改原来的空盒子,而是把函数内部的node标签撕下来,重新贴到一个新的Node实例盒子上。
  4. 外层函数的node标签根本没动,还是贴在原来的None空盒子上,所以返回node.val时,自然会报错说NoneType没有val属性。

简单总结一下:

  • 当你传递可变对象(比如列表、字典、自定义类实例)时,函数内部修改对象的内部状态,外部能看到变化;
  • 当你传递不可变对象(比如None、整数、字符串)时,函数内部对参数的赋值操作,只会创建局部变量,不会影响外部的变量。

内容的提问来源于stack exchange,提问作者Michael Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:44:55