簡體   English   中英

cython中的函數更改numpy數組類型

[英]Function in cython changes numpy array type

我正在使用Cython和numpy,但是與更改numpy數組元素的dtype的cython函數有關的問題很奇怪。 奇怪的是,僅在實際指定數組的輸入類型時才更改dtype。

我在Ubuntu 18.04上使用Cython == 0.29.11,numpy == 1.15.4,python 3.6。

# cyth.pyx
cimport numpy as np

def test(x):
    print(type(x[0]))

def test_np(np.ndarray[np.uint32_t, ndim=1] x):
    print(type(x[0]))

現在對這個文件進行cythonize並使用以下功能:

>>> from cyth import test, test_np
>>> import numpy as np
>>> a = np.array([1, 2], dtype=np.uint32)
>>> test(a)
<class 'numpy.uint32'>
>>> test_np(a)
<class 'int'>

因此test按預期方式工作,打印輸入數組中第一個元素的類型-uint32。 但是test_np實際上確保了傳入數組的類型為uint32,現在顯示了常規Python int作為第一個元素的類型。

即使試圖強制元素為正確的類型也不起作用,即使用:

def test_np(np.ndarray[np.uint32_t, ndim=1] x):
    cdef np.uint32_t el
    el = x[0]
    print(type(el))

仍然導致

>>> test_np(a)
<class 'int'>

在理解這一差異方面的任何幫助將不勝感激。

Cython不會更改數組的類型,但是會返回類型稍有不同的元素。

numpy-array中的數據存儲為32位無符號整數的連續字段。 訪問x[0]意味着創建一個Python對象(因為Python解釋器無法處理原始C-int) np.uint32對於每個numpy- np.uint32都有專用的包裝器類,並返回一個np.uint32

另一方面,Cython將所有簡單的C整數類型(例如longint等)映射到Python整數(有意義)上。

現在,當導入numpy時, x[0]不再意味着使用numpy數組的__getitem__() (它將返回np.uint32 ),而是C整數(在這種情況下為unsigned 4byte),它將轉換為Python整數,因為“ return XXX”表示在def函數中表示結果必須是Python對象。

這確實意味着該數組具有不同的類型-Cython將這些類型映射為Python對象時,它們的映射方式不同。


如果要以np.uint32 -objects的形式訪問數據,則可以調用__getitem__而不是[..] (Cython將[..]轉換為對原始C數據的訪問權):

%%cython
cimport numpy as np

def test_np(np.ndarray[np.uint32_t, ndim=1] x):
    print(type(x[0]))                     # int
    print(type(x.__getitem__(0)))         # numpy.uint32

當您使用類型化的內存視圖而不是ndarray時,直接調用__getitem__會返回內存視圖的Python整數__getitem__而不調用基礎ndarray的__getitem__而是在C級訪問數據。 調用底層對象的__getitem__進行內存視圖:

def test_np(np.uint32_t[:] x):
    print(type(x[0]))
    print(type(x.base.__getitem__(0))) # instead of x.__getitem__(0)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM