Python引用传参时函数内排序后外部列表未排序问题
Python列表传参与排序作用域问题解答
问题背景
现有Python目录遍历代码逻辑为:遍历指定目录,收集文件名前缀为so、后缀为log的文件路径存入list_name列表。代码在自定义listdir函数内部对传入的list_name执行sorted()排序,运行时出现如下现象:
- 函数内部排序后打印
list_name为有序状态 - 返回主函数作用域后,传入的
list_name仍为未排序状态,必须在主函数中再次执行sorted()才能得到有序列表
对应两个核心疑问:
- 为什么主函数中的
list_name没有保留函数内的排序结果? - 如果函数内的
list_name是局部变量,为什么全局定义的list_name会被追加文件路径元素?
问题解答
主函数列表未保留排序结果的原因
核心原因是sorted()是非原地操作的内置函数:它不会修改传入的原列表,只会基于原列表的元素生成一个全新的、排好序的列表作为返回值。
你在函数内打印的有序结果,本质是sorted()生成的新列表副本,你并没有将这个新副本重新绑定到原列表的引用上,主作用域中的原列表从头到尾没有被修改,自然保持无序状态。
如果要在函数内直接修改原列表实现排序,应该使用列表自带的.sort()方法,这个方法是原地修改列表本身,不会生成新对象。两种写法的差异可以参考如下示例:
# 错误写法:sorted不修改原列表 def func1(arr): res = sorted(arr) print("函数内sorted结果:", res) # 有序,是新对象 # 正确写法:.sort()原地修改 def func2(arr): arr.sort() print("函数内sort结果:", arr) # 有序,修改的是原对象 origin_arr = [3,1,2] func1(origin_arr) print("主函数原列表(func1执行后):", origin_arr) # 输出[3,1,2],无变化 func2(origin_arr) print("主函数原列表(func2执行后):", origin_arr) # 输出[1,2,3],已排序
全局列表被追加元素的原因
这里首先要纠正一个认知误区:执行追加操作时,函数内并没有创建独立的局部list_name变量。
Python的参数传递遵循传对象引用规则:将全局列表传入函数时,函数内的形参和全局的实参指向内存中同一个列表对象,这时候分两类操作场景:
- 执行
append()、extend()、切片赋值这类原地修改操作时,改动直接作用在内存中那个共有的列表对象上,全局列表自然会同步出现新增元素 - 执行变量赋值操作(比如
list_name = sorted(list_name))时,本质是让函数内的list_name这个变量名,重新绑定到sorted()返回的新列表对象上。从赋值这一刻开始,函数内的list_name和全局原列表就断开了关联,后续对这个新列表的所有操作都不会影响全局的原列表。
简单来说:变量名只是贴在内存对象上的标签,直接改对象内容时,所有指向这个对象的标签都能看到变化;如果把局部标签贴到新对象上,原来指向旧对象的外部标签不会受到任何影响。
内容的提问来源于stack exchange,提问作者Iaoceot
相关产品推荐
相关产品推荐

