根据我能找到的文档,在使用花式索引时,会返回副本而不是视图。但是,我无法弄清楚在分配给另一个数组时它的行为是什么,例如:
A = np.arange(0,10)
B = np.arange(-10,0)
fancy_slice = np.array([0,3,5])
A[fancy_slice] = B[fancy_slice]
我了解A
只会收到__setitem__
的来电,而B
会接到__getitem__
的来电。我关心的是在将值复制到A
之前是否创建了中间数组。
答案 0 :(得分:1)
解释器将解析代码并发出方法调用:
B
A
方法在传递给numpy
方法之前已完全评估。 temp = B[idx]
A[idx] = temp
del temp
不会改变Python解释器或其语法。相反,它只是添加了函数,对象和方法。
从功能上讲,它应该等同于
timeit
我们可以确定一些In [712]: A = np.zeros(10000,int)
In [713]: B = np.arange(10000)
In [714]: idx = np.arange(0,10000,100)
In [715]: timeit A[idx] = B[idx]
1.2 µs ± 3.24 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [716]: %%timeit
...: temp = B[idx]
...: A[idx] = temp
...:
1.11 µs ± 0.669 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
。
add.at
有一些替代的功能/方法,例如copyto
,place
,put
,copyto
,可能会在没有中间版的情况下复制一些副本,但我没有&#39他们使用了很多。这个索引分配足够好 - 大部分时间。
In [718]: wh = np.zeros(A.shape, bool)
In [719]: wh[idx] = True
In [721]: np.copyto(A, B, where=wh)
In [722]: timeit np.copyto(A, B, where=wh)
7.47 µs ± 9.92 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
copyto
因此,即使没有计时布尔掩码的构造,put
也会慢一些。
take
和In [727]: timeit np.put(A,idx, np.take(B,idx))
7.98 µs ± 8.34 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
并不是更好:
{{1}}
答案 1 :(得分:1)
创建一个中间数组。 已创建。 NumPy没有看到
A[fancy_slice] = B[fancy_slice]
它看到了
B[fancy_slice]
单凭,不知道上下文是什么。定义此操作以创建一个新数组,NumPy创建一个新数组。
然后,NumPy看到了
A[fancy_slice] = <the array created by the previous operation>
并将数据复制到A
。