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

Python传递对象参数未被覆盖的疑问:代码对比与传参机制探究

为什么两段Python代码修改参数后原变量结果不同?

嘿,这个问题问得特别到位,刚好能帮你把Python参数传递和对象可变性这俩核心概念掰明白,咱们一步步拆解清楚。

先把两段代码和对应的输出列出来,方便对比:

第一段代码(自定义类实例)

class MyClass:
    def __init__(self, x):
        self.x = x
def myfunct(arg):
    arg.x += 1
    return arg
a = MyClass(0)
print(a.x)
b = myfunct(a)
print(a.x)
print(b.x)

输出:0 1 1

第二段代码(整数)

def myfunct(arg):
    arg += 1
    return arg
c = 0
print(c)
d = myfunct(c)
print(c)
print(d)

输出:0 0 1

核心原因:可变对象 vs 不可变对象

Python里的对象本质上分成两类,这是造成差异的关键:

  • 可变对象:比如自定义类实例、列表、字典这类,它们的内部状态可以直接修改,不用重新生成一个新对象。
  • 不可变对象:像整数、字符串、元组这种,它们的内部状态是固定的,任何看似“修改”的操作,其实都是生成了一个全新的对象。

结合按赋值传参机制分析

Python的参数传递是按赋值传参(passing by assignment),说白了就是:当你把变量传给函数时,其实是把变量指向的对象的引用,复制了一份给函数的形参。

第一段代码的运行逻辑:

  1. a = MyClass(0):a指向一个MyClass的实例对象,这个对象的x属性是0。
  2. 调用myfunct(a):函数的形参arg拿到了和a一样的引用——也就是指向同一个实例对象。
  3. arg.x += 1:这是在直接修改这个实例对象的内部属性,因为实例是可变对象,所以这个修改会直接作用在a指向的那个对象上。
  4. 返回arg:返回的还是同一个实例的引用,所以b和a指向的是同一个对象。
    最后自然a.x和b.x都是1,原对象被实实在在修改了。

第二段代码的运行逻辑:

  1. c = 0:c指向整数对象0,而整数是不可变对象。
  2. 调用myfunct(c):形参arg拿到了c指向的整数0的引用。
  3. arg += 1:这可不是修改原有的0,而是生成了一个新的整数对象1,然后把arg的引用改成指向这个新对象——原来的0完全没动。
  4. 返回arg:返回的是新对象1的引用,所以d指向新对象,但c还是牢牢指着原来的0。
    所以最后c还是0,d是1,原对象根本没被碰过。

一句话总结

当你在函数里操作参数时:

  • 如果参数是可变对象,修改它的内部属性(比如arg.x、arg.append())会直接影响原变量指向的对象;
  • 如果参数是不可变对象,任何“修改”操作都会生成新对象,对原变量指向的对象毫无影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:29:48