python - 关于切片数组覆盖python中的字典赋值的问题
问题描述
我有以下代码。我正在尝试将 numpy 数组 EPtmp(CH4 用零填充,NO 用 1 填充)添加到字典中,键为“CH4”和“NO”。在 for 循环的第一次迭代中,零数组与键 CH4 正确关联。在第二次迭代中,ones 数组覆盖了先前写入的 CH4 键和新的 NO 键的条目。如果我从 EPtmp[:] = EP 中删除切片,使其改为 EPtmp = EP,它可以完美地工作而不会覆盖先前写入的数组。这似乎与 Python 分配或访问内存的方式有关,但我还没有在文档中找到任何内容来解释这种行为。任何想法为什么切片 [:] 会导致字典覆盖?
import numpy as np
species_names = ['O2', 'CH4', 'NO', 'N2', 'O', 'CH3', 'H', 'HO2', 'N2O', 'NO2', 'NNH']
target_index_species = [1,2]
EP_spec_dict = {}
EPtmp = np.zeros(len(species_names),'d')
for index_target_local, index_target_global in enumerate(target_index_species):
EP = np.ones(len(species_names))*index_target_local
EPtmp[:] = EP
print("Going to add",species_names[index_target_global],"EP tmp",EPtmp)
EP_spec_dict[species_names[index_target_global]] = EPtmp
print("Full dict",EP_spec_dict)
解决方案
EPtmp = EP
使 EPtmp 成为对 EP 的引用,这意味着如果您更改 EPtmp,您实际上是在更改 EP,因为它们是同一个数组。
EPtmp[:]
= EP 复制 EP,因此更改 EPtmp 不会更改 EP。
在您的控制台中尝试以下操作:
a=[1,2]
b=[0,0]
a=b
a[0]=5
b
Out[13]: [5, 0]
和
a=[1,2]
b=[0,0]
a[:]=b
a[0]=5
b
Out[18]: [0, 0]
但是切片也可以反过来。如果您有b = a
然后通过执行 a = [] 设置 a,则 b 不会更改,因为您正在创建一个新的 a。但是,如果您不创建新的 a 而是用 显式覆盖旧的a[:]=[]
a ,则 b 会更改。
尝试:
a=[1,2]
b=a
c=b
a=[1,3] #doesn't change b and c
b[:]=[1,4] #changes c
基本上,a=b 意味着 a 是指向 b 指向内存的指针,而 a[:]=b 意味着将 b 的内容写入 a 指向的位置。
因此,在您的示例中,您的字典包含指向 EPtmp 的指针。经过EP_spec_dict[species_names[index_target_global]] = EPtmp
现在,如果您使用 制作一个新的 EPtmp EPtmp=EP
,它位于不同的内存部分,并且EP_spec_dict[species_names[index_target_global]]
仍然指向旧 EPtmp 的内存部分。但是,使用 EPtmp[:]=EP 您只是覆盖了 EPtmp 的内存内容,而不是创建一个新内容。
推荐阅读
- python - Python List 造成内存不足?
- python - 如何在不使用 For 循环的情况下检查布尔值?
- javascript - 如何在 Node.js 服务器中使用 C++ 应用程序?
- java - 在用户单击之前面板不可见
- java - 由于密码错误,无法通过 Spring App 连接到已经存在的 H2 数据库文件源
- php - Laravel 迁移抛出“SQLSTATE[HY000] [2002] php_network_getaddresses”异常
- javascript - 如何通过鼠标移动角度旋转鼠标跟随的正方形?
- django - 如何使用特定的电子邮件地址 Django 注册用户?
- simulation - 导出 Anylogic 实验的结果
- python - exec 和 eval 如何将 __builtins__ 添加到给定的环境中?