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

Tôi không biết làm thế nào __contains__ hoạt động cho ndarrays. Tôi không thể tìm thấy tài liệu liên quan khi tôi tìm kiếm nó. Làm thế nào nó hoạt động? Và liệu nó có được ghi chép ở bất cứ đâu không?Làm thế nào để __contains__ hoạt động cho ndarrays?

+0

Nhìn vào nguồn, sau đó. – Marcin

+4

@Marcin: Nguồn được chôn ở đâu đó trong một đống C mà tôi không hiểu cấu trúc. Một phần lớn của nó thậm chí còn được tạo tự động, và phần lớn nó được sao chép để xử lý các loại dtypes khác nhau và những khác biệt khác. Tôi sẽ không đào sâu hết nếu tôi không phải làm vậy. – user2357112

+3

http://www.mail-archive.com/[email protected]/msg31578.html dường như có câu trả lời. –

Trả lời

6

Tôi tìm thấy nguồn cho ndarray.__contains__, trong numpy/core/src/multiarray/sequence.c. Như một lời nhận xét ở các bang nguồn,

thing in x 

tương đương với

(x == thing).any() 

cho một ndarray x, không phụ thuộc vào kích thước của xthing. Điều này chỉ có ý nghĩa khi thing là vô hướng; kết quả phát sóng khi thing không phải là vô hướng gây ra các kết quả lạ mà tôi quan sát được, cũng như các số lẻ như array([1, 2, 3]) in array(1) mà tôi không nghĩ là thử. Nguồn chính xác là

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

Có vẻ như numpy 's __contains__ đang làm một cái gì đó như thế này cho một trường hợp 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] công trình vì các yếu tố thứ 0 của hàng đầu tiên phù hợp với nguyên tố thứ 0 của [1,7]. Tương tự với [1,2] v.v. Với [2,6], số 6 khớp với số 6 ở hàng cuối cùng. Với [2,3], không có yếu tố nào khớp với một hàng ở cùng một chỉ mục. [1, 2, 3] là tầm thường vì các hình dạng không khớp.

Xem this để biết thêm và cũng có thể this ticket.

+0

Dường như với tôi rằng 'tất cả' sẽ hữu dụng hơn so với' bất kỳ', tôi tự hỏi tại sao các nhà phát triển 'numpy' lại chọn việc triển khai' __contains__' này. – Akavall

+1

@Akavall Dường như khả năng tương thích với Chữ số. Trong Numeric, giá trị boolean của mảng được giả định là 'True' nếu nó chứa ít nhất một phần tử khác 0. Numpy làm tăng các ngoại lệ khi một người cố gắng sử dụng một mảng như một boolean, nói rằng ta nên sử dụng 'any()' hoặc 'all()'. Trong trường hợp này, '__contains __()' API đang buộc Numpy giải thích một mảng trong một bối cảnh boolean, và cho điều này, họ quyết định đi với những gì Numeric đã làm. Nhưng tôi đồng ý, nó thực sự khó hiểu và tôi không biết nếu * bất cứ ai * phụ thuộc vào hành vi này của '__contains __()'. –

+0

Điểm tốt về khả năng tương thích. Cảm ơn. – Akavall

Các vấn đề liên quan