Numpy代码中tmp_k与qhum值同步变化的原因问询
问题:修改qhum时tmp_k同步变化的原因分析
问题重现
你提供的MCVE代码执行后,出现修改qhum数值时tmp_k同步变化的异常,我补充了未定义的hgt变量以便代码可运行,完整代码如下:
import numpy as np press_in = [98100,97400,95300,94100] tmp_in = [285.6,289,290.4,290] qhum_in = [0.0087998267,0.0089221532,0.0095515558,0.0080244699] psfc = 980.085*1e2 q2m = 0.00907988 t2m = 285.615 nlev = 4 + 1 press = np.zeros(nlev,dtype = 'float32') press[:] = np.nan press[1:] = press_in tmp_k = np.zeros(nlev,dtype = 'float32') tmp_k[:] = np.nan tmp_k[1:] = tmp_in qhum = np.zeros(nlev,dtype = 'float32') qhum[:] = np.nan qhum[1:] = qhum_in tmp_k[0] = t2m # 补充定义hgt变量以避免报错 hgt = np.full(nlev, np.nan, dtype='float32') qhum[0] = q2m press[0] = psfc np.put(press,np.squeeze(np.where(press >= psfc))[1:],np.nan) missing = np.logical_or(np.logical_or(np.isnan(press),np.isnan(qhum)),np.logical_or(np.isnan(tmp_k),np.isnan(hgt))) allmissing = np.zeros(nlev,dtype = 'float32') allmissing[:] = np.nan tmp_k = tmp_k[np.logical_not(np.isnan(np.where(missing,np.nan,tmp_k)))] allmissing[:len(tmp_k)] = tmp_k tmp_k = allmissing qhum = qhum[np.logical_not(np.isnan(np.where(missing,np.nan,qhum)))] allmissing[:len(qhum)] = qhum qhum = allmissing
原因分析
这个问题的核心是NumPy数组的引用赋值机制,我用大白话给你拆解:
你可以把NumPy数组想象成一个装数据的盒子,变量名(比如tmp_k、qhum、allmissing)就是贴在盒子上的标签。
- 你先创建了
allmissing这个盒子,里面装满了nan。 - 执行
tmp_k = allmissing时,你并没有复制一个新盒子,只是给allmissing这个旧盒子贴了第二个标签tmp_k——现在两个标签指向同一个盒子,动其中一个,另一个的内容肯定会变。 - 接着你执行
allmissing[:len(qhum)] = qhum,直接把qhum的数据塞进了这个共享盒子里,此时tmp_k对应的盒子内容已经被悄悄替换了。 - 最后执行
qhum = allmissing,相当于给这个盒子贴了第三个标签qhum,最终tmp_k和qhum完全指向同一个盒子,数值自然完全一致。
解决办法
如果你想让tmp_k和qhum各用各的盒子,需要使用数组复制操作,而不是直接贴标签:
- 用
tmp_k = allmissing.copy()代替tmp_k = allmissing,这会复制出一个全新的盒子给tmp_k - 同理,
qhum = allmissing.copy()代替qhum = allmissing
修改后的关键代码片段:
allmissing = np.zeros(nlev,dtype = 'float32') allmissing[:] = np.nan tmp_k = tmp_k[np.logical_not(np.isnan(np.where(missing,np.nan,tmp_k)))] allmissing[:len(tmp_k)] = tmp_k tmp_k = allmissing.copy() # 复制出独立的新数组 # 重置allmissing,准备存放qhum的数据 allmissing[:] = np.nan qhum = qhum[np.logical_not(np.isnan(np.where(missing,np.nan,qhum)))] allmissing[:len(qhum)] = qhum qhum = allmissing.copy() # 复制出独立的新数组
这样修改后,tmp_k和qhum就会指向各自独立的内存空间,修改其中一个不会影响另一个。
内容的提问来源于stack exchange,提问作者Vinayak Huggannavar
相关产品推荐
相关产品推荐

