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

为什么Python列表等对象在函数内索引修改时会改变外部原值

Python函数内修改列表/数组同步影响外部原对象的原因与解决方案

核心原因解释

你的认知偏差核心是没有区分Python中赋值操作和可变对象原地修改操作的差异,以及Python变量本质是对象引用的底层逻辑:

  1. 所有Python变量都是指向内存中对象的引用,不是值本身。对象分为两类:
    • 不可变对象:int、float、str、元组等,无法修改对象本身的内容,只要修改就会生成新的对象
    • 可变对象:列表、字典、numpy数组等,支持直接修改对象本身的内容,不需要生成新对象
  2. 你的第一个示例中,函数内部执行i=1属于局部赋值操作,相当于在函数局部作用域新建了一个名为i的局部变量,和全局的i是完全独立的两个引用,自然不会修改全局i的值。
  3. 你的第二个示例中,函数内部执行img[0] = img[0] + 100属于可变对象的原地修改操作:
    函数内部没有定义名为img的局部变量,所以会直接使用全局的img引用,这个引用指向内存中存储的列表对象,通过索引赋值是直接修改该内存对象的内容,因此全局的img读取到的就是修改后的结果。

避免原对象被修改的方案

要防止函数内操作影响外部原可变对象,只需要在操作前对可变对象做拷贝,基于拷贝后的本地副本操作即可,具体方案如下:

  • 单层结构的可变对象(比如一维列表、一维numpy数组)用浅拷贝即可:
    列表可以用list.copy()方法或者切片list[:],numpy数组可以用.copy()方法
  • 嵌套结构的可变对象(比如二维列表、嵌套字典)需要用深拷贝,导入copy模块调用copy.deepcopy()方法即可

正确示例代码

import copy

# 建议将可变对象作为参数传入,不要直接调用全局变量,逻辑更易维护
def fun(input_img):
    # 拷贝生成本地副本,后续所有操作仅修改副本
    local_img = copy.deepcopy(input_img)
    local_img[0] = local_img[0] + 100
    return 'done', local_img

img = [0, 1]
status, modified_img = fun(img)
print(img == [0, 1]) # 输出True,原对象未被修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:54:03