Как работает __contains__ для ndarrays?

>>> 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. Я не мог найти соответствующую документацию, когда я ее искал. Как это работает? И документирована ли она где-нибудь?

Ответы

Ответ 1

Я нашел источник ndarray.__contains__, в numpy/core/src/multiarray/sequence.c. Как комментарий в исходных состояниях,

thing in x

эквивалентно

(x == thing).any()

для ndarray x, независимо от размеров x и thing. Это имеет смысл только тогда, когда 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;
}

Ответ 2

Кажется, что numpy __contains__ делает что-то подобное для 2-го случая:

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 th первой строки соответствует элементу 0 th [1,7]. То же самое с [1,2] и т.д. С [2,6], 6 соответствует 6 в последней строке. С [2,3] ни один из элементов не соответствует строке в том же индексе. [1, 2, 3] является тривиальным, поскольку формы не совпадают.

Подробнее см. , а также этот билет.