代码之家  ›  专栏  ›  技术社区  ›  Paul Panzer

使用python范围对象索引到numpy数组

  •  2
  • Paul Panzer  · 技术社区  · 6 年前

    我以前看过一两次,但似乎找不到任何官方文档:使用python range 对象作为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和它的docs之间的细微差异并非完全没有听说过,也不一定表示不打算使用某个特性(参见示例) here ).

    那么,有人知道为什么会这样吗?如果它是一个预期的特性,那么确切的语义是什么/它有什么好处?有没有什么归纳?

    2 回复  |  直到 6 年前
        1
  •  1
  •   javidcf    6 年前

    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 升起。

        2
  •  1
  •   Paul Panzer    6 年前

    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
    
    推荐文章