为何全局numpy变量传入函数后改变,普通变量却不变?如何避免?
为什么
a_np变了,a却没变化? 这本质是Python里可变对象和不可变对象的传递逻辑差异,结合你描述的现象,我给你拆解下:
假设你的代码大概是这样的(完美匹配你说的结果):
import numpy as np # 全局变量 a = [1, 2, 3] a_np = np.array([1, 2, 3]) def glb_mod(arr): # 对列表重新赋值 if isinstance(arr, list): arr = [999, 999, 999] # 对numpy数组修改元素 elif isinstance(arr, np.ndarray): arr[0] = 999 # 调用函数 glb_mod(a) glb_mod(a_np) print(a) # 输出 [1, 2, 3] print(a_np) # 输出 [999, 2, 3]
背后的核心逻辑:
- 对于列表
a:函数里的arr = [999...]其实是给局部变量arr重新绑定了一个全新的列表对象,根本没碰原来的全局列表a,所以原a完全没变。 - 对于numpy数组
a_np:numpy数组属于可变对象,传递给函数的是它的内存引用。函数里的arr[0] = 999是直接通过引用修改了原数组的元素值,所以全局的a_np自然就跟着变了。
怎么让
a_np传入函数后不被修改? 核心思路就是别直接传原对象,传它的副本,这样函数内部折腾的是副本,原对象毫发无损。有两种简单的实现方式:
方式1:调用函数时传入副本
直接用numpy数组的copy()方法生成副本再传入:
# 传入a_np的副本,原数组不会被修改 glb_mod(a_np.copy()) print(a_np) # 还是原来的 [1,2,3]
方式2:在函数内部先做副本再操作
如果不想改调用方式,就在函数内部先复制一份传入的数组,之后只操作副本:
def glb_mod(arr): # 先创建原数组的副本 arr_copy = arr.copy() # 只修改副本 arr_copy[0] = 999 # 可以把修改后的副本返回给调用者 return arr_copy # 调用后原数组不变,修改后的结果存在变量里 modified_arr = glb_mod(a_np) print(a_np) # [1,2,3] print(modified_arr) # [999,2,3]
额外补个小知识点:如果想让列表a被函数修改怎么办?
刚才的例子里列表没被修改是因为重新赋值了局部变量。如果要修改原列表,得直接操作列表的内容,比如用切片赋值:
def glb_mod(arr): if isinstance(arr, list): arr[:] = [999, 999, 999] # 直接修改原列表的内容 elif isinstance(arr, np.ndarray): arr_copy = arr.copy() arr_copy[0] = 999 return arr_copy glb_mod(a) print(a) # 现在会输出 [999,999,999]
内容的提问来源于stack exchange,提问作者DIY-DS
相关产品推荐
相关产品推荐

