我在Pandas source上见过几次这样的东西:
def nancorr(ndarray[float64_t, ndim=2] mat, bint cov=0, minp=None):
# ...
N, K = (<object> mat).shape
这意味着名为mat
的NumPy ndarray
是type-casted的Python对象。*
经过进一步的检查,似乎使用这种方法是因为如果不是这样,就会出现编译错误。我的问题是:为什么首先需要这种类型转换?在
这里有几个例子。This答案很简单,元组打包在Cython中不像在Python中那样有效——但这似乎不是元组解包的问题。(不管怎样,这都是一个很好的答案,我不想挑刺。)
执行以下脚本,shape.pyx
。它将在编译时失败,并出现“Cannot convert'npy_intp*”to Python object“
但是,问题本身似乎不是tuple解包。这将以相同的错误失败。在
def test_castobj(ndarray[float64_t, ndim=2] arr):
cdef:
# Py_ssize_t b1, b2
ndarray[float64_t, ndim=2] zeros
zeros = np.zeros(arr.shape, dtype=np.float64)
return zeros
看起来,这里没有元组解包。元组是np.zeros
的第一个参数。在
def test_castobj(ndarray[float64_t, ndim=2] arr):
"""This works"""
cdef:
Py_ssize_t b1, b2
ndarray[float64_t, ndim=2] zeros
b1, b2 = (<object> arr).shape
zeros = np.zeros((<object> arr).shape, dtype=np.float64)
return b1, b2, zeros
这也很管用(也许是最令人困惑的):
def test_castobj(object[float64_t, ndim=2] arr):
cdef:
tuple shape = arr.shape
ndarray[float64_t, ndim=2] zeros
zeros = np.zeros(shape, dtype=np.float64)
return zeros
示例:
>>> from shape import test_castobj
>>> arr = np.arange(6, dtype=np.float64).reshape(2, 3)
>>> test_castobj(arr)
(2, 3, array([[0., 0., 0.],
[0., 0., 0.]]))
或许这与arr
是一个记忆视图有关?但在黑暗中
另一个例子是Cythondocs:
cpdef int sum3d(int[:, :, :] arr) nogil:
cdef size_t i, j, k
cdef int total = 0
I = arr.shape[0]
J = arr.shape[1]
K = arr.shape[2]
在这种情况下,简单地索引arr.shape[i]
就可以防止这个错误,我觉得很奇怪。在
这也适用于:
def test_castobj(object[float64_t, ndim=2] arr):
cdef ndarray[float64_t, ndim=2] zeros
zeros = np.zeros(arr.shape, dtype=np.float64)
return zeros
你说得对,这和Cython下的元组解包无关。在
原因是,} (在python中称为
cnp.ndarray
不是一个普通的numpy数组(这意味着一个具有python已知接口的numpy数组),而是一个numpy的C实现的^{np.array
):实际上,}-field (
^{pr2}$shape
映射到底层C-stuct的^{npy_intp *shape "dimensions"
),而不是简单的npy_intp *dimensions
)。这是个把戏,所以你可以写作它的外观(以及某种程度上的感觉)就像numpy的python属性
shape
被调用一样。但事实上,一条直接通向潜在的C-stuct的捷径就走了。在顺便说一句,调用python-
shape
代价很高:必须创建一个元组并用dimensions
中的值填充,然后访问第0个元素。另一方面,Cython的方法要便宜得多——只要使用正确的元素。在但是,如果您还想访问数组的python属性,则必须将其强制转换为普通python对象(即,忘记这是一个}解析为tuple属性调用。在
ndarray
),然后通过通常的python机制将{因此,基本上,即使这很方便,您也不希望像pandas代码中那样在一个紧循环中访问numpy数组的维度,而是使用更详细的变量来提高性能:
^{3}$为什么你能在函数签名中写
object[cnp.float64_t]
或类似的东西,我觉得很奇怪——参数很明显被解释为一个简单的对象。也许这只是个虫子。在相关问题 更多 >
编程相关推荐