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

Python函数内操作列表副本仍修改原列表的问题求助

问题描述

我编写了两个函数:

  • recursiveScanText:在对象数组中查找y0值匹配的元素,返回对应文本字符串
  • mergeSimilarText:合并y坐标相近(±5)的对象

我已经在mergeSimilarText中对输入列表执行了copy()操作,但运行代码后原输入列表tmp仍被修改。我定位到问题出在第26行修改BOLD_OBJ["text"]的操作,但不清楚原因。之前误以为这是字典数组而非数组数组,无需使用深拷贝,尝试修改拷贝方式也没解决问题。

原代码

def recursiveScanText(BOLD_OBJ_LIST:list, Y_VALUE: int, output: list):
    if BOLD_OBJ_LIST[0]["y0"] == Y_VALUE:
        output.append(BOLD_OBJ_LIST[0]["text"])
        BOLD_OBJ_LIST.pop(0)
        if BOLD_OBJ_LIST == []:
            return output
        output = recursiveScanText(BOLD_OBJ_LIST, Y_VALUE, output)
        return output
    else:
        return output
 
def mergeSimilarText(BOLD_OBJ_LIST: list):
    """Merges the objects of a list of objects if they are at a similar (±5) Y coordinate"""
    OUTPUT = []
    RECURSIVE_SCAN_OUTPUT = []
    BOLD_OBJ_LIST = BOLD_OBJ_LIST.copy()
 
    for BOLD_OBJ_INDEX in range(len(BOLD_OBJ_LIST)):
        if len(BOLD_OBJ_LIST) > 0 and BOLD_OBJ_INDEX < len(BOLD_OBJ_LIST):
            BOLD_OBJ = BOLD_OBJ_LIST[0]
 
            BOLD_CHAR_STRING = recursiveScanText(BOLD_OBJ_LIST, BOLD_OBJ_LIST[BOLD_OBJ_INDEX]["y0"], RECURSIVE_SCAN_OUTPUT)
 
            RECURSIVE_SCAN_OUTPUT = []
 
            BOLD_OBJ["text"] = "".join(BOLD_CHAR_STRING)
            OUTPUT.append(BOLD_OBJ)
 
    return OUTPUT
 
tmp = [
{'y0': 762.064, 'text': '177'}, 
{'y0': 762.064,  'text': '7'}, 
{'y0': 114.8281, 'text': 'Q'}, 
{'y0': 114.8281, 'text': 'u'}, 
{'y0': 114.8281, 'text': 'e'}, 
{'y0': 114.8281, 'text': 's'}, 
{'y0': 114.8281, 'text': 't'}, 
{'y0': 114.8281, 'text': 'i'}, 
{'y0': 114.8281, 'text': 'o'}, 
{'y0': 114.8281, 'text': 'n'}, 
{'y0': 114.8281, 'text': ' '}, 
{'y0': 114.8281, 'text': '1'}, 
{'y0': 114.8281, 'text': '7'}, 
{'y0': 114.8281, 'text': ' '}, 
{'y0': 114.8281, 'text': 'c'}, 
{'y0': 114.8281, 'text': 'o'}, 
{'y0': 114.8281, 'text': 'n'}, 
{'y0': 114.8281, 'text': 't'}, 
{'y0': 114.8281, 'text': 'i'}, 
{'y0': 114.8281, 'text': 'n'}, 
{'y0': 114.8281, 'text': 'u'}, 
{'y0': 114.8281, 'text': 'e'}, 
{'y0': 114.8281, 'text': 's'}, 
{'y0': 114.8281, 'text': ' '}, 
{'y0': 114.8281, 'text': 'o'}, 
{'y0': 114.8281, 'text': 'n'}, 
{'y0': 114.8281, 'text': ' '}, 
{'y0': 114.8281, 'text': 'p'}, 
{'y0': 114.8281, 'text': 'a'}, 
{'y0': 114.8281, 'text': 'g'}, 
{'y0': 114.8281, 'text': 'e'}, 
{'y0': 114.8281, 'text': ' '}, 
{'y0': 114.8281,'text': '9'}]
 
print(mergeSimilarText(tmp))
print(tmp)
问题原因
  1. 列表浅拷贝的局限性:BOLD_OBJ_LIST.copy()是浅拷贝,它只复制了列表本身的结构,但列表中的每个字典元素还是和原列表tmp里的字典指向同一个内存地址。也就是说,新列表和原列表共享里面的字典对象。
  2. 字典修改的直接影响:当你执行BOLD_OBJ["text"] = "".join(BOLD_CHAR_STRING)时,本质是在修改共享的字典对象内容,自然会同步反映到原列表tmp中对应的元素上。
解决方法

提供两种可行的解决方案:

方案1:使用深拷贝

通过copy.deepcopy()创建完全独立的列表,里面的每个字典都会被完整复制,修改新列表中的字典不会影响原列表。

修改后的mergeSimilarText函数:

import copy

def mergeSimilarText(BOLD_OBJ_LIST: list):
    """Merges the objects of a list of objects if they are at a similar (±5) Y coordinate"""
    OUTPUT = []
    RECURSIVE_SCAN_OUTPUT = []
    # 替换为深拷贝
    BOLD_OBJ_LIST = copy.deepcopy(BOLD_OBJ_LIST)
 
    for BOLD_OBJ_INDEX in range(len(BOLD_OBJ_LIST)):
        if len(BOLD_OBJ_LIST) > 0 and BOLD_OBJ_INDEX < len(BOLD_OBJ_LIST):
            BOLD_OBJ = BOLD_OBJ_LIST[0]
 
            BOLD_CHAR_STRING = recursiveScanText(BOLD_OBJ_LIST, BOLD_OBJ_LIST[BOLD_OBJ_INDEX]["y0"], RECURSIVE_SCAN_OUTPUT)
 
            RECURSIVE_SCAN_OUTPUT = []
 
            BOLD_OBJ["text"] = "".join(BOLD_CHAR_STRING)
            OUTPUT.append(BOLD_OBJ)
 
    return OUTPUT

方案2:创建新字典再修改

不直接修改原字典引用,而是复制字典内容生成新对象,再修改text字段,避免影响原列表中的字典。

修改mergeSimilarText中修改text的部分:

# 替换原BOLD_OBJ["text"]修改和OUTPUT.append的代码
new_obj = BOLD_OBJ.copy()  # 复制原字典生成新对象
new_obj["text"] = "".join(BOLD_CHAR_STRING)
OUTPUT.append(new_obj)
额外优化提示

原recursiveScanText函数的逻辑存在冗余,且mergeSimilarText中的循环在执行pop(0)后会出现索引错位问题,可以考虑用迭代方式替代递归,同时优化循环逻辑,避免不必要的索引判断。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:05:17