带有对象dtypes的numpy.all的奇怪行为

发布于 2021-01-29 15:01:52

给定一个数组dtype=objectnumpy.all/any返回最后一个对象。例如:

>>> from string import ascii_lowercase
>>> x = np.array(list(ascii_lowercase), dtype=object)
>>> x.all()
'z'

在研究此问题时,除了这篇看似无关的SO帖子,我无法找到其他东西,使我发现这是numpy中的一个公开错误(截至2015年3月):第一个报告更相关的问题。发布此信息,以便其他人对此有所了解,可以更有效地找到此信息。

关注者
0
被浏览
72
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    numpy版本1.8.2np.anynp.all表现为经典短路逻辑和/或功能。想到LISP行为。Pythonandor运算符可以做到这一点。

    一些例子:

    In [203]: np.all(np.array([[1,2],1,[],[1,2,3]],dtype=object))
    Out[203]: []
    
    In [204]: np.any(np.array([[1,2],1,[],[1,2,3]],dtype=object))
    Out[204]: [1, 2]
    
    In [205]: np.any(np.array([0,[],[1,2],1,[],[1,2,3]],dtype=object))
    Out[205]: [1, 2]
    
    In [206]: np.all(np.array([True,False,[1,2],1,[],[1,2,3]],dtype=object))
    Out[206]: False
    

    np.all返回逻辑上为False的第一项;否则最后一项。np.any第一项在逻辑上为True;否则最后一项。

    在LISP世界中,这被认为是有用的功能。一旦结果明确,它不仅会停止评估元素,而且可以使用该返回值的标识。

    有没有一种方法可以使用and/or运算符和某种map或reduce来复制此行为?

    In [8]: 0 or [] or [1,2] or 1 or [1,2,3]
    Out[8]: [1, 2]
    
    ???([0,[],[1,2],1,[1,2,3]])
    

    如评论中所建议:

    In [26]: reduce(lambda a,b:a and b, np.array([1,2,3,[1,2,3]],dtype=object))
    Out[26]: [1, 2, 3]
    

    这实际上可能不会使整个回路短路。而是使每个步骤都短路,并将该值向前传播。使用lambda a,b:b and a将返回列表中的第一项,而不是最后一项。时序可以用来测试它是否遍历整个数组(或没有遍历整个数组)。


    np.allufunc定义为的np.logical_and.reduce

    https://github.com/numpy/numpy/blob/master/numpy/core/_methods.py

    umr_all = um.logical_and.reduce
    def _all(a, axis=None, dtype=None, out=None, keepdims=False):
        return umr_all(a, axis, dtype, out, keepdims)
    

    logical_and对于dtype = object在c源中定义

    https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/funcs.inc.src

    /* Emulates Python's 'a and b' behavior */
    static PyObject *
    npy_ObjectLogicalAnd(PyObject *i1, PyObject *i2)
    

    类似的np.any。数字dtype版本在其他地方定义。

    有一个补丁迫使np.all/any返回dtype=bool。但是通过np.logical_all直接调用,您可以自己控制。

    In [304]: np.logical_or.reduce(np.array([0,[1,2,3],4],dtype=object))
    Out[304]: [1, 2, 3]
    
    In [305]: np.logical_or.reduce(np.array([0,[1,2,3],4],dtype=object),dtype=bool)
    Out[305]: True
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看