使用 python 范围对象索引到 numpy 数组
Using python range objects to index into numpy arrays
我以前看过一两次,但我似乎找不到任何关于它的官方文档:Using python range
objects as indices in numpy.
import numpy as np
a = np.arange(9).reshape(3,3)
a[range(3), range(2,-1,-1)]
# array([2, 4, 6])
让我们触发一个索引错误,以确认范围不在合法索引方法的官方范围(双关语)中:
a['x']
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
现在,numpy 与其文档之间的细微差异并非完全闻所未闻,并不一定表示某个功能不是预期的(参见示例 )。
那么,有人知道为什么这行得通吗?如果它是一个预期的功能,那么确切的语义是什么/它有什么用?是否有任何 ND 概括?
不是一个正确的答案,但是太长了无法评论。
事实上,它似乎适用于任何可索引对象:
import numpy as np
class MyIndex:
def __init__(self, n):
self.n = n
def __getitem__(self, i):
if i < 0 or i >= self.n:
raise IndexError
return i
def __len__(self):
return self.n
a = np.array([1, 2, 3])
print(a[MyIndex(2)])
# [1 2]
我认为 NumPy 代码中的相关行在 core/src/multiarray/mapping.c
中的注释下方:
/*
* Some other type of short sequence - assume we should unpack it like a
* tuple, and then decide whether that was actually necessary.
*/
但我不完全确定。出于某种原因,如果您删除 if i < 0 or i >= self.n: raise IndexError
,即使有 __len__
,它也会挂起,因此在某些时候它似乎正在遍历给定对象,直到引发 IndexError
。
总结一下(感谢评论中的@WarrenWeckesser):此行为实际上已记录在案。人们只需要意识到 range
对象是 python 序列 in the strict sense.
所以这只是花式索引的一个例子。但是请注意,它非常慢:
>>> a = np.arange(100000)
>>> timeit(lambda: a[range(100000)], number=1000)
12.969507368048653
>>> timeit(lambda: a[list(range(100000))], number=1000)
7.990526253008284
>>> timeit(lambda: a[np.arange(100000)], number=1000)
0.22483703796751797
我以前看过一两次,但我似乎找不到任何关于它的官方文档:Using python range
objects as indices in numpy.
import numpy as np
a = np.arange(9).reshape(3,3)
a[range(3), range(2,-1,-1)]
# array([2, 4, 6])
让我们触发一个索引错误,以确认范围不在合法索引方法的官方范围(双关语)中:
a['x']
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
现在,numpy 与其文档之间的细微差异并非完全闻所未闻,并不一定表示某个功能不是预期的(参见示例
那么,有人知道为什么这行得通吗?如果它是一个预期的功能,那么确切的语义是什么/它有什么用?是否有任何 ND 概括?
不是一个正确的答案,但是太长了无法评论。
事实上,它似乎适用于任何可索引对象:
import numpy as np
class MyIndex:
def __init__(self, n):
self.n = n
def __getitem__(self, i):
if i < 0 or i >= self.n:
raise IndexError
return i
def __len__(self):
return self.n
a = np.array([1, 2, 3])
print(a[MyIndex(2)])
# [1 2]
我认为 NumPy 代码中的相关行在 core/src/multiarray/mapping.c
中的注释下方:
/*
* Some other type of short sequence - assume we should unpack it like a
* tuple, and then decide whether that was actually necessary.
*/
但我不完全确定。出于某种原因,如果您删除 if i < 0 or i >= self.n: raise IndexError
,即使有 __len__
,它也会挂起,因此在某些时候它似乎正在遍历给定对象,直到引发 IndexError
。
总结一下(感谢评论中的@WarrenWeckesser):此行为实际上已记录在案。人们只需要意识到 range
对象是 python 序列 in the strict sense.
所以这只是花式索引的一个例子。但是请注意,它非常慢:
>>> a = np.arange(100000)
>>> timeit(lambda: a[range(100000)], number=1000)
12.969507368048653
>>> timeit(lambda: a[list(range(100000))], number=1000)
7.990526253008284
>>> timeit(lambda: a[np.arange(100000)], number=1000)
0.22483703796751797