切片表示法不会在内存中创建新副本
Posted
技术标签:
【中文标题】切片表示法不会在内存中创建新副本【英文标题】:Slice notation isn't creating a new copy in memory 【发布时间】:2018-04-05 18:20:09 【问题描述】:我使用 scipy 和 imread() 将图像导入为 RGB。假设我想分离出“R”组件并将其复制到内存中的新对象。下面的代码有效:
import scipy as sp
import scipy.misc as misc
import matplotlib.pyplot as plt
%matplotlib inline
pic = misc.imread("ARBITRARY IMAGE.png");
r = pic[:,:,0].copy()
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])
输出预期:
0
255
但是我通过以下路径到达那里,我不知道为什么它们不起作用:
r = pic[:,:,0]
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])
输出:
0
0
很公平,我从here 中获得了语法提示,它涉及使用像b = a[:]
这样的切片而不是单层。怎么样:
r = pic[:]
r[0,0,0] = 0
print(r[0,0,0])
print(pic[0,0,0])
或添加一个额外的步骤:
r = pic[:]
r= r[:,:,0]
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])
仍然输出:
0
0
它是一个数组而不是一个列表,但数组的this answer 暗示这种语法应该没问题。基本上,当我在示例中使用切片符号时,为什么没有在内存中创建新对象?我假设我错过了其他东西,我的谷歌搜索似乎告诉我语法应该有效。感谢您的帮助!
【问题讨论】:
变量pic
可能不是一个普通的数组,而是一些带有重载切片运算符的对象,它不会创建副本,而是引用相同数据的视图。例如。如果我没记错的话,numpy 也不喜欢创建副本。
【参考方案1】:
other question you linked 使用了不正确的术语;它询问的是 Python lists,而您使用的是 Numpy 数组。切片列表确实会为您提供所选范围的副本,但 slicing an array gives you a view 会改为。您对视图所做的更改会反映在原始视图中。
使用 Numpy 数组,您需要使用 copy()
来获得一个单独的副本,您可以在不影响原始数据的情况下对其进行更改。这是一种设计选择,因为 Numpy 数组通常非常大,您不想无意中复制它们。
【讨论】:
警告如果您使用的是 32 位 python np.array.copy 可能是一个昂贵的内存操作(numpy 需要连续内存) @David Duh 我什至没想到他们使用了错误的术语。乔然,我在这里不是必须的,但是你有其他选择吗?或者我应该尽量避免使用这样的数组进行复制以上是关于切片表示法不会在内存中创建新副本的主要内容,如果未能解决你的问题,请参考以下文章
在 pentaho 的 CDE 仪表板的表组件中创建新列,表示 2 列的总和