Python堆操作函数两种调用方式差异的技术问询
两种
heap_add_or_replace调用方式的差异分析 咱们直接点出核心问题:这两种调用方式的差异根源在于Python列表的传参特性,以及你函数内部对堆的处理逻辑——你在函数里创建了新列表,但没同步回外部传入的原列表。
方式一:接收函数返回的新列表
在方式一中,你每次调用heap_add_or_replace后,都把函数返回的结果赋值给了变量(比如a、b,其实更合理的是复用同一个变量,比如triplet_heap = heap_add_or_replace(triplet_heap, ...))。
你的函数逻辑是:
- 先把新三元组加到传入的堆里
- 两次
sorted生成新的排序后的列表 - 去重后返回这个全新的列表
所以每次调用后,变量都指向了这个经过排序、去重的正确堆结构,自然输出符合预期。
方式二:直接传入列表但未接收返回值
方式二的问题出在你以为函数会修改传入的new_heap,但实际上函数内部并没有真正修改它,咱们一步步拆解你的函数代码:
heap.append(triplet):这一步确实修改了外部的new_heap——因为列表是可变对象,函数内部对它的原地修改会影响外部。所以第一次调用后,new_heap里会有那个三元组。vertexSort = sorted(heap, key=lambda x: x[0]):sorted函数返回的是新列表,不会修改原heap(也就是外部的new_heap)。lenSort = sorted(vertexSort, key=lambda x: x[1]):同样,这又是一个新列表。heap = remvDuplicate(lenSort):这里的heap是函数的局部变量,现在它指向了去重后的新列表,但外部的new_heap还是指向原来的那个列表(只被append过一次的原始列表)。
函数结束后,外部的new_heap根本没拿到排序、去重后的结果,第二次调用只是又append了一个新元素,所以最后输出的是两次append的原始顺序,自然不符合预期。
如何让方式二生效?
有两种修改思路:
思路1:函数内部原地修改传入的列表
不要创建新列表,直接在原列表上做去重、排序操作,比如:
def heap_add_or_replace(heap, triplet): # 先检查是否有重复vertex,有则替换,无则添加 has_duplicate = False for idx, item in enumerate(heap): if item[0] == triplet[0]: heap[idx] = triplet has_duplicate = True break if not has_duplicate: heap.append(triplet) # 按length升序原地排序 heap.sort(key=lambda x: x[1]) return heap
这样函数内部直接修改传入的列表,方式二调用时new_heap会被正确更新。
思路2:方式二中也接收函数返回值
和方式一一样,每次调用都把返回值赋值给new_heap:
new_heap = list() new_heap = heap_add_or_replace(new_heap,((2,3),0.9,(1,0))) print("the new heap is: " + str(new_heap)) new_heap = heap_add_or_replace(new_heap,((7,2),0.3,(2,2))) print("the new heap is: " + str(new_heap))
总结
两种调用方式的本质差异是:
- 方式一通过接收函数返回的新列表,获取了经过处理的正确堆结构;
- 方式二因为函数内部只修改了局部变量指向的新列表,没有同步到外部传入的原列表,导致原列表只保留了原始的
append数据,没有排序和去重。
内容的提问来源于stack exchange,提问作者Ammar_Taha
相关产品推荐
相关产品推荐

