MST

星途 面试题库

面试题:Python按引用调用与函数参数传递

考虑如下Python代码:def func(lst): lst.append(4); return lst; my_list = [1, 2, 3]; result = func(my_list.copy()); 请详细分析my_list和result在函数调用前后的内存变化,以及按引用调用机制在这个过程中是如何起作用的。另外,解释为什么这里使用了my_list.copy(),如果不使用会有什么不同结果。
33.2万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

1. 内存变化分析

  • 函数调用前
    • my_list 是一个包含 [1, 2, 3] 的列表对象,在内存中占据一定的空间,其内存地址为 id(my_list)
    • result 尚未定义。
  • 函数调用中
    • func 函数接收 my_list.copy() 创建的新列表对象(与 my_list 内容相同但内存地址不同),这个新列表对象在内存中有自己独立的空间,其内存地址为 id(lst)(这里 lst 是函数参数)。
    • 执行 lst.append(4) 操作,修改的是新列表对象(即 lst 指向的对象),在其内存空间中增加一个元素 4
    • 函数返回修改后的 lst,并赋值给 result。此时 result 指向这个包含 [1, 2, 3, 4] 的新列表对象。
  • 函数调用后
    • my_list 保持不变,仍然是 [1, 2, 3],因为传递给函数的是其副本,其内存地址 id(my_list) 没有改变。
    • result[1, 2, 3, 4],指向一个新的内存地址 id(result)(即 func 函数中 lst 指向的内存地址)。

2. 按引用调用机制

在Python中,函数参数传递是按对象引用传递。当 func(my_list.copy()) 调用时,实际上传递的是 my_list.copy() 创建的新列表对象的引用(内存地址)。在函数内部对 lst 的操作(如 lst.append(4)),是通过这个引用找到对应的列表对象并进行修改。但由于传递的是副本的引用,所以 my_list 本身不受影响。

3. 使用 my_list.copy() 的原因及不使用的结果

  • 使用 my_list.copy() 的原因:为了避免函数内部对传入列表的修改影响到原始列表 my_list。这样可以保证 my_list 的数据完整性,函数操作的是一个独立的副本。
  • 不使用 my_list.copy() 的结果:如果直接传递 my_list 给函数(即 result = func(my_list)),函数内部对 lst 的修改(lst.append(4))会直接影响到 my_list。因为此时 lstmy_list 指向同一个内存地址,修改 lst 就等同于修改 my_list。最终 my_listresult 都会是 [1, 2, 3, 4]