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

Python字典追加数组时旧条目被更新的问题排查

ArrayList性能测试中字典条目共享sizes数组的问题

在实现支持自定义扩容算法的ArrayList时,编写analyzePerformance函数测试性能时发现:每次向字典中添加包含不同长度sizes数组的条目后,旧字典条目里的sizes数组也会被更新为最长的版本。

相关代码

ArrayList类代码

class ArrayList:
    def __init__(self, growfn):
        '''Initializes the empty ArrayList with the specified growth function.'''
        self.size = 0
        self.used = 0
        self.array = []
        self.grow = growfn

    def get(self, index):
        if index < self.size:
            return self.array[index]
        # exception handling
        return None

    def add(self, value):
        if self.used == self.size:
            newSize = self.grow(self.size)
            if newSize <= self.size:
                # exception handling
                return
            newArray = self.array[:]+[None for i in range(self.size,newSize)]
            self.array = newArray
            self.size = newSize
        self.array[self.used] = value
        self.used = self.used + 1
        return None

测试函数代码

def analyzePerformance(nList, gfn, tries):
    data = []
    sizes_array = []
    averages = []
    arr = ArrayList(gfn)
    for num in nList:
        for j in range(tries):
            current_size = 0
            start = time()
            while arr.size < num:
                arr.add(None)
                if arr.size != current_size:
                    sizes_array.append(arr.size)
                    current_size = arr.size
            end = time()
            averages.append(end - start)
        data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array})) 
    return data

调用代码

def main():
    for result in analyzePerformance([1,10,100], double, 11):
        print(result)

当前输出

{'grow': <function double at 0x7f3274eb4f28>, 'N': 1, 'seconds': 3.034418279474432e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 10, 'seconds': 4.659999500621449e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 100, 'seconds': 7.369301535866477e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}

期望输出

{'grow': <function double at 0x7f3274eb4f28>, 'N': 1, 'seconds': 3.034418279474432e-07, 'sizes': [1]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 10, 'seconds': 4.659999500621449e-07, 'sizes': [1, 2, 4, 8, 16]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 100, 'seconds': 7.369301535866477e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}

问题原因

Python中列表是可变对象,你在analyzePerformance函数里只初始化了一次sizes_array,所有添加到data列表的字典,其sizes字段都引用了同一个sizes_array对象。后续循环中对sizes_array的append操作,会直接修改这个共享的列表,导致所有旧字典条目里的sizes都跟着变化。

解决方案

有两种可行的修复方式:

方式1:每次循环重新初始化sizes_array

将sizes_array = []放到for num in nList:循环内部,确保每个num对应的测试都使用独立的列表:

def analyzePerformance(nList, gfn, tries):
    data = []
    averages = []
    arr = ArrayList(gfn)
    for num in nList:
        sizes_array = []  # 移到循环内部,每次循环创建新列表
        for j in range(tries):
            current_size = 0
            start = time()
            while arr.size < num:
                arr.add(None)
                if arr.size != current_size:
                    sizes_array.append(arr.size)
                    current_size = arr.size
            end = time()
            averages.append(end - start)
        data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array})) 
    return data

方式2:添加字典时创建列表副本

如果需要保留外部的sizes_array,可以在添加到字典时,创建当前列表的副本,避免引用共享:

# 修改data.append的行,用copy()创建副本
data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array.copy()})) 
# 或者用list()转换:sizes: list(sizes_array)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:30:49