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

Python传列表到函数append时修改原列表的原因及解决方法

结论

该现象是Python的完全正常的预期行为,不属于bug,核心由Python的参数传递规则和可变/不可变对象的特性决定。

原理说明

Python的参数传递采用传对象引用(也称为传赋值)的规则:

  • 所有变量存储的都是指向内存中实际对象的引用,变量本身没有类型,类型归属于它指向的对象。
  • 调用函数传参时,本质是把实参持有的对象引用赋值给函数的形参,形参和实参最初指向内存中的同一个对象,不会自动生成对象的拷贝。

你观察到的修改结果差异,来自操作对象的类型和操作方式不同:

  • 列表、自定义类实例属于可变对象:调用append()、修改实例属性这类操作属于原地修改,直接改动了引用指向的对象本身,由于形参和实参指向同一个对象,函数内外都会观测到改动。
  • 整数、字符串、元组属于不可变对象:不存在原地修改的方法,你写的variable += 1本质是创建了一个值为variable+1的新整数对象,再让函数内部的形参指向这个新对象,外部的实参仍然指向原来的整数对象,因此外部观测不到变化。
规避方法

根据业务场景选择对应方案即可:

  • 传入参数时主动传递副本
    如果不希望函数内部修改影响外部原始数据,传参时传入对象的副本即可。普通一维列表可以用浅拷贝生成独立副本:
    # 以下三种写法都可以生成列表的浅拷贝
    mc.main_function_list(list_.copy())
    mc.main_function_list(list_[:])
    mc.main_function_list(list(list_))
    
    对于自定义类实例的场景,如果不希望修改原实例的属性,也可以在传参前生成实例的拷贝,或者在函数内部操作属性的副本而非原属性。
  • 函数内部避免原地修改,返回新对象
    尽量不在函数内部对传入的可变对象做原地修改操作,而是基于传入值生成新对象返回,由调用方自行决定是否用返回值替换原数据:
    def main_function_list(self,variable):
        # 拼接生成新列表,不改动传入的原列表
        return variable + [1]
    
  • 嵌套可变对象使用深拷贝
    如果传入的可变对象内部还嵌套了其他可变对象(比如列表套列表、列表存自定义实例),浅拷贝只会复制最外层结构,内层元素仍然是共享引用,此时需要用标准库copy的deepcopy方法生成完全独立的完整副本:
    import copy
    mc.main_function_list(copy.deepcopy(list_))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:36:47