2013-08-19 24 views
15
>>> x = numpy.array([[1, 2], 
...     [3, 4], 
...     [5, 6]]) 
>>> [1, 7] in x 
True 
>>> [1, 2] in x 
True 
>>> [1, 6] in x 
True 
>>> [2, 6] in x 
True 
>>> [3, 6] in x 
True 
>>> [2, 3] in x 
False 
>>> [2, 1] in x 
False 
>>> [1, 2, 3] in x 
False 
>>> [1, 3, 5] in x 
False 

我不知道如何__contains__适用于ndarrays。我找到相关文档时找不到相关文档。它是如何工作的?它在任何地方都有记录吗?__contains__如何为ndarrays工作?

+0

然后看看源代码。 – Marcin

+4

@Marcin:源代码被埋在一堆C中,我不了解它的结构。它的很大一部分甚至是自动生成的,其中很大一部分被复制来处理不同的dtype和其他差异。如果我不必这样做,我不会深究。 – user2357112

+3

http://www.mail-archive.com/[email protected]/msg31578.html似乎有答案。 –

回答

6

我找到了ndarray.__contains__的源文件,在numpy/core/src/multiarray/sequence.c。在源状态的评论,

thing in x 

相当于

(x == thing).any() 

用于ndarray x,不管xthing的尺寸。这只有在thing是标量时才有意义;广播的结果当thing不是一个标量导致我观察到的奇怪结果,以及像我想不想尝试的array([1, 2, 3]) in array(1)这样的奇怪结果。确切来源是

static int 
array_contains(PyArrayObject *self, PyObject *el) 
{ 
    /* equivalent to (self == el).any() */ 

    PyObject *res; 
    int ret; 

    res = PyArray_EnsureAnyArray(PyObject_RichCompare((PyObject *)self, 
                 el, Py_EQ)); 
    if (res == NULL) { 
     return -1; 
    } 
    ret = array_any_nonzero((PyArrayObject *)res); 
    Py_DECREF(res); 
    return ret; 
} 
5

好像numpy__contains__正在做这样的事情对于一个2-d情况:

def __contains__(self, item): 
    for row in self: 
     if any(item_value == row_value for item_value, row_value in zip(item, row)): 
      return True 
    return False 

[1,7]作品,因为第一行的0个元素的[1,7]0个元素相匹配。与[1,2]相同等[2,6],6匹配最后一行中的6。在[2,3]中,没有一个元素与同一索引处的行匹配。由于形状不匹配,因此很简单。

请参阅this以获取更多信息,并且还需要this ticket

+0

在我看来,'all'会比'any'更实用,我想知道为什么'numpy'开发者选择了'__contains__'的这个实现。 – Akavall

+1

@Aavall似乎是为了与数字兼容。在Numeric中,如果数组的布尔值至少包含一个非零元素,则假定为“True”。当你尝试使用数组作为布尔值时,Numpy会引发异常,并说应该使用'any()'或'all()'。 在这种情况下,'__contains __()'API迫使Numpy在布尔上下文中解释数组,为此,他们决定使用Numeric做的事情。 但我同意,这真的很让人困惑,我不知道是否有人*依赖于__contains __()'的行为。 –

+0

关于兼容性的好处。谢谢。 – Akavall