2013-08-19 26 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