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

为何Python函数会修改传入的列表参数?AoC2022 Day5问题求助

问题:Python列表传入函数后原列表被修改的原因

我在完成Advent of Code 2022第5天题目时遇到一个问题:把stacks列表传入A.py的calculate函数后,原列表居然被修改了,导致后续B.py运行出错。我通过将列表转为元组再转回列表的显式拷贝方式解决了问题,但想知道Python这种行为的原因,这是不是语言的内置特性?

相关代码

main.py

import A
import B

with open("input.txt", "r") as file:
    data = [_ for _ in file.read().split("\n")]

stacks = []
controls = []

stackData = data[:8]
for i in range(9):
    stack = ""
    for row in stackData:
        box = row[(i*4 + 1)]
        stack += box
    stacks.append(stack)

for i in range(len(stacks)):
    stacks[i] = stacks[i].strip()

controlData = data[10:]
for row in controlData:
    control = row.split(" ")

    amount = int(control[1])
    spot = int(control[3])
    destination = int(control[5])

    controls.append([amount, spot, destination])


print(f"Answer to section A is: {A.calculate(stacks, controls)}")
print(f"Answer to section B is: {B.calculate(stacks, controls)}")

A.py

def calculate(data, controls):
    answer = ""

    for control in controls:
        amount = control[0]
        start = control[1] - 1
        destination = control[2] - 1

        boxes = data[start][:amount]
        boxes = boxes[::-1]
        data[start] = data[start][amount:]
        data[destination] = boxes + data[destination]

    for stack in data:
        answer += stack[0]

    return answer

B.py

def calculate(data, controls):
    answer = ""

    for control in controls:
        amount = control[0]
        start = control[1] - 1
        destination = control[2] - 1

        boxes = data[start][:amount]
        data[start] = data[start][amount:]
        data[destination] = boxes + data[destination]

    for stack in data:
        answer += stack[0]

    return answer

解答

这是Python的内置特性,核心原因在于:

  1. 列表是可变对象:Python中的列表属于可变类型,意味着可以在原对象上直接修改内容(比如修改元素、增删元素等)。
  2. 参数传递是引用传递:当你把stacks传入函数时,函数参数data拿到的是原列表对象的引用——也就是说,data和stacks指向内存中同一个列表。

在A.py的calculate函数里,你执行了data[start] = data[start][amount:]、data[destination] = boxes + data[destination]这类操作,这些都是直接修改data指向的列表对象内容,自然会影响到外部的stacks。等A的计算完成,stacks已经是被修改后的状态,再传入B.py的calculate时,用的是修改后的列表,结果必然出错。

你用“转元组再转回列表”的方式解决问题,本质是创建了原列表的浅拷贝——新列表和原列表是两个独立的对象,函数里修改的是拷贝后的列表,不会影响原列表,这样B就能使用原始的stacks计算了。

类似的浅拷贝方式还有:

  • 使用列表切片:stacks[:]
  • 使用copy模块:import copy; copy.copy(stacks)
  • 列表自身的copy方法:stacks.copy()

因为你的列表元素是字符串(不可变类型),浅拷贝就足够保证两个列表完全独立。如果列表里还有可变子对象,可能需要用到深拷贝copy.deepcopy()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:31:12