面试题答案
一键面试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
。因为此时lst
和my_list
指向同一个内存地址,修改lst
就等同于修改my_list
。最终my_list
和result
都会是[1, 2, 3, 4]
。