Python列表传参疑问:为何print(v,m,n)输出全为[3,6,9]?
Python列表操作的输出疑惑解答
题目选项
- a) [1, 2, 3], [2, 4, 6], [3, 6, 9]
- b) [3, 6, 9], [3, 6, 9], [3, 6, 9]
- c) [1, 2, 3], [1, 2, 3], [3, 6, 9]
- d) [1, 2, 3], [1, 2, 3], [2, 4, 6]
- e) [3, 6, 9], [1, 2, 3], [3, 6, 9]
问题详情
我是Python初学者,运行以下代码后,实际输出和预期完全不符,搞不懂为什么:
运行代码
def f1(v): for elem in v: elem *= 2 return v def f2(m): for i in range(len(m)): m[i] *= 3 return m v = [1,2,3] m = f1(v) n = f2(v) print(v, m, n)
预期输出
[1, 2, 3] [1, 2, 3] [3, 6, 9]
实际输出
[3, 6, 9] [3, 6, 9] [3, 6, 9]
我原本以为调用f1(v)后m应该是[1,2,3],调试时执行n = f2(v)前也确实看到m是这个值,但最终三个变量输出全是[3,6,9],正确答案是选项b,求解释原因。
核心原因:列表是可变对象,传递的是引用
Python里列表属于可变对象,当你把列表传给函数时,传的不是列表的副本,而是它在内存中的引用。也就是说,函数内部对这个列表的修改,会直接改动原列表本身。
逐行拆解执行过程
- 初始化列表:
v = [1,2,3],内存中生成一个列表对象,v指向这个对象。 - 调用
f1(v):- 函数里的参数
v和外部的v是同一个列表的引用。 - 循环里的
elem *= 2:elem是列表元素的临时变量,因为整数是不可变对象,修改elem只是给这个临时变量重新赋值了一个新整数,根本没改动原列表里的元素。所以f1返回的还是原列表的引用,m和v指向同一个列表,此时两者都是[1,2,3]。
- 函数里的参数
- 调用
f2(v):- 函数接收的参数同样指向原列表对象。
- 循环里的
m[i] *=3是直接通过索引修改列表元素,这会直接改变原列表的内容,原列表从[1,2,3]变成[3,6,9]。 f2返回的还是原列表的引用,所以n也指向这个被修改后的列表。
- 打印输出:此时
v、m、n都指向内存中同一个列表对象,这个对象已经被f2改成了[3,6,9],所以三者输出完全一样。
解释你的调试现象
你调试时在执行n = f2(v)前看到m是[1,2,3],那是因为f2还没执行,原列表还没被修改。但执行f2(v)后,原列表被改变,而m和v指向同一个对象,所以m的值也会同步变成[3,6,9]——你看到的调试值是修改前的状态,修改后所有指向该对象的变量都会跟着变。
如何得到预期输出
如果想让m、n是独立的列表,需要在函数内部创建列表副本,比如:
- 修改
f1:把返回语句改成return v.copy()(或者return list(v)、return v[:]) - 修改
f2:先复制列表再修改,示例代码:
def f2(m): new_m = m.copy() for i in range(len(new_m)): new_m[i] *= 3 return new_m
这样每个函数返回的都是新的列表对象,不会影响原列表,就能得到你预期的输出。
内容的提问来源于stack exchange,提问作者fcoser
相关产品推荐
相关产品推荐

