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

Python递归归并排序代码疑问:未赋值为何lefthalf变量会改变

为啥无返回值的mergeSort能修改lefthalf?

哈哈,这个问题戳中了Python中可变对象的核心特性!咱们结合你的代码一步步捋清楚:

首先先补全你没写完的归并排序完整逻辑(毕竟merge阶段是关键):

def merge(alist, lefthalf, righthalf):
    i = j = k = 0
    # 合并两个有序子列表到alist中
    while i < len(lefthalf) and j < len(righthalf):
        if lefthalf[i] < righthalf[j]:
            alist[k] = lefthalf[i]
            i += 1
        else:
            alist[k] = righthalf[j]
            j += 1
        k += 1
    # 处理剩余元素
    while i < len(lefthalf):
        alist[k] = lefthalf[i]
        i += 1
        k += 1
    while j < len(righthalf):
        alist[k] = righthalf[j]
        j += 1
        k += 1

def mergeSort(alist):
    print("Splitting ",alist)
    if len(alist)>1:
        mid = len(alist)//2
        lefthalf = alist[:mid]
        righthalf = alist[mid:]
        print("Before left call------>",lefthalf)
        mergeSort(lefthalf)
        print("after left call------>",lefthalf)
        mergeSort(righthalf)
        merge(alist,lefthalf,righthalf)

核心原因:Python列表是可变对象

在Python中,列表属于可变(mutable)对象,当你把列表作为参数传给函数时,传递的是对象的引用(不是列表的副本)。这意味着:

  • 函数内部对这个列表的直接修改,会直接作用于内存中的原列表对象
  • 哪怕函数没有返回值,外部的变量(比如这里的lefthalf)指向的还是同一个内存对象,所以能看到修改后的结果

具体到你的代码流程

假设初始lefthalf是[54,26]:

  1. 调用mergeSort(lefthalf),递归拆分到子列表[54]和[26](长度为1,不再拆分)
  2. 进入merge阶段:递归返回时,会调用merge函数,把传入的alist(也就是当前递归层的lefthalf)替换成合并后的有序列表[26,54]
  3. 当递归回到上层时,原来的lefthalf变量指向的还是同一个列表对象,所以它的值已经变成了排序后的结果

对比理解:不可变对象的差异

如果是整数、字符串这类不可变对象,函数内部修改只会创建新对象,不会影响外部变量。比如:

def add_one(num):
    num += 1

a = 5
add_one(a)
print(a)  # 输出还是5,因为整数不可变,函数里的num是新对象

而列表这种可变对象,函数操作的是原对象的引用,所以修改会直接生效~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:23:28