传递数组副本与引用为何仅影响特定Python代码片段的执行效率?
为何传递列表副本/引用仅影响snippet2的执行效率?
我对比了两个代码片段的执行效率:snippet1先通过if判断再执行while循环,snippet2直接用while循环判断。测试代码如下:
import time def snippet1(nums): nums.sort() c = 0 for i in range(1, len(nums)): if nums[i] <= nums[i-1]: while nums[i] <= nums[i-1]: nums[i] += 1 c += 1 return c def snippet2(nums): nums.sort() c = 0 for i in range(1, len(nums)): while nums[i] <= nums[i-1]: nums[i] += 1 c += 1 return c # Sample list of numbers nums = [5, 1, 3, 2, 4, 2, 1, 6, 5, 8, 9, 7, 3, 2, 5] # Measure time for snippet1 start_time = time.time() snippet1(nums) # 此处原代码是nums[:]改为nums end_time = time.time() print("Time for snippet1:", end_time - start_time) # Measure time for snippet2 start_time = time.time() snippet2(nums) end_time = time.time() print("Time for snippet2:", end_time - start_time)
原本结果符合预期,但将驱动代码中的nums[:]改为nums后,仅snippet2的执行时间出现大幅变化:
- 使用
nums[:]时:snippet1平均耗时约1.5e-05秒,snippet2平均约1.5e-05秒; - 使用
nums时:snippet1平均耗时约2e-05秒,snippet2平均约5e-06秒。
我无法理解为何传递数组副本或引用仅会影响该代码片段?
使用nums[:]的执行结果:
Time for snippet1: 1.52587890625e-05 Time for snippet2: 1.430511474609375e-05 === Code Execution Successful ===
使用nums的执行结果:
Time for snippet1: 2.0265579223632812e-05 Time for snippet2: 5.245208740234375e-06 === Code Execution Successful ===
问题原因分析
- 列表的可变性是核心:当直接传递
nums(引用)时,snippet1执行后会直接修改原列表——把它排序并调整成严格递增的序列。 - 调用
snippet2时,它首先执行nums.sort(),但此时列表已经是完全有序的了!Python的list.sort()在列表已排序的情况下会触发O(n)的快速优化路径,几乎不消耗时间。同时,因为列表已经是严格递增的,snippet2里的while循环一次都不会执行,所以耗时骤降。 - 当用
nums[:]传递副本时,snippet1和snippet2各自拿到独立的原列表副本,两者都要完成完整的排序+循环调整操作,因此耗时接近。 - 为什么
snippet1的耗时没有变化?因为不管是原列表还是副本,snippet1里的if+while逻辑都会完整遍历:即使列表已经有序,if判断会跳过while,但整个循环的遍历、判断步骤一个不少,所以耗时基本稳定。
内容的提问来源于stack exchange,提问作者Hassan Mustafa
相关产品推荐
相关产品推荐

