我对cython中的这么多int
数据类型感到有点挣扎。
np.int, np.int_, np.int_t, int
我认为纯python中的int
等同于np.int_
,那么np.int
来自哪里?我从numpy找不到文件?另外,为什么np.int_
存在,因为我们已经有int
?
在cython中,我猜int
在用作cdef int
或ndarray[int]
时会变成C类型,当用作int()
时,它会像蟒蛇一样停留吗?
C np.int_
相当于long
吗?所以cdef long
与cdef np.int_
相同?
在什么情况下我应该使用np.int_t
代替np.int
?例如cdef np.int_t
,ndarray[np.int_t]
...
有人可以简单解释这些类型的错误使用会如何影响已编译的cython代码的性能吗?
答案 0 :(得分:28)
这有点复杂,因为名称根据上下文有不同的含义。
int
在Python中
int
通常只是一个Python类型,它具有任意精度,这意味着你可以在其中存储任何可以想象的整数(只要你有足够的内存)。
>>> int(10**50)
100000000000000000000000000000000000000000000000000
但是,当您将dtype
用作NumPy数组时,它将被解释为np.int_
1 。哪个是不的任意精度,它将与C的long
具有相同的大小:
>>> np.array(10**50, dtype=int)
OverflowError: Python int too large to convert to C long
这也意味着以下两个是等价的:
np.array([1,2,3], dtype=int)
np.array([1,2,3], dtype=np.int_)
作为Cython类型标识符,它有另一种含义,这里它代表c类型int
。它的精度有限(通常为32位)。您可以将其用作Cython类型,例如在使用cdef
:
cdef int value = 100 # variable
cdef int[:] arr = ... # memoryview
作为cdef
或cpdef
函数的返回值或参数值:
cdef int my_function(int argument1, int argument2):
# ...
ndarray
的“通用”:
cimport numpy as cnp
cdef cnp.ndarray[int, ndim=1] val = ...
对于类型转换:
avalue = <int>(another_value)
可能还有更多。
在Cython中,但作为Python类型。您仍然可以调用int
并获得“Python int”(任意精度),或者将其用于isinstance
或dtype
作为np.array
的参数。这里的上下文很重要,因此转换为Python int
与转换为C int:
cdef object val = int(10) # Python int
cdef int val = <int>(10) # C int
np.int
实际上这很容易。它只是int
的别名:
>>> int is np.int
True
所以上面的所有内容也适用于np.int
。但是,除非在cimport
ed包上使用它,否则不能将其用作类型标识符。在这种情况下,它表示Python整数类型。
cimport numpy as cnp
cpdef func(cnp.int obj):
return obj
这将使obj
成为Python整数而不是NumPy类型:
>>> func(np.int_(10))
TypeError: Argument 'obj' has incorrect type (expected int, got numpy.int32)
>>> func(10)
10
我对np.int
的建议:尽可能避免使用它。在Python代码中,它等同于int
,在Cython代码中它也等同于Pythons int
,但如果用作类型标识符,它可能会使您和阅读代码的每个人感到困惑!这当然让我很困惑......
np.int_
实际上它只有一个含义:它是一个 Python类型,代表一个标量NumPy类型。你像Pythons int
一样使用它:
>>> np.int_(10) # looks like a normal Python integer
10
>>> type(np.int_(10)) # but isn't (output may vary depending on your system!)
numpy.int32
或者您使用它来指定dtype
,例如使用np.array
:
>>> np.array([1,2,3], dtype=np.int_)
array([1, 2, 3])
但你不能在Cython中将它用作类型标识符。
cnp.int_t
这是np.int_
的类型标识符版本。这意味着你不能将它用作dtype参数。但您可以将其用作cdef
声明的类型:
cimport numpy as cnp
import numpy as np
cdef cnp.int_t[:] arr = np.array([1,2,3], dtype=np.int_)
|---TYPE---| |---DTYPE---|
此示例(希望如此)显示带有尾随_t
的类型标识符实际上表示使用 dtype 而没有尾随t
的数组类型。你不能用Cython代码交换它们!
NumPy中还有几种数字类型我将包含一个包含NumPy dtype和Cython类型标识符的列表以及也可以在Cython中使用的C类型标识符。但它基本上取自the NumPy documentation和Cython NumPy pxd
file:
NumPy dtype Numpy Cython type C Cython type identifier
np.bool_ None None
np.int_ cnp.int_t long
np.intc None int
np.intp cnp.intp_t ssize_t
np.int8 cnp.int8_t signed char
np.int16 cnp.int16_t signed short
np.int32 cnp.int32_t signed int
np.int64 cnp.int64_t signed long long
np.uint8 cnp.uint8_t unsigned char
np.uint16 cnp.uint16_t unsigned short
np.uint32 cnp.uint32_t unsigned int
np.uint64 cnp.uint64_t unsigned long
np.float_ cnp.float64_t double
np.float32 cnp.float32_t float
np.float64 cnp.float64_t double
np.complex_ cnp.complex128_t double complex
np.complex64 cnp.complex64_t float complex
np.complex128 cnp.complex128_t double complex
实际上np.bool_
:cnp.npy_bool
和bint
都有Cython类型,但它们目前都不能用于NumPy数组。对于标量cnp.npy_bool
将只是一个无符号整数,而bint
将是一个布尔值。不知道那里发生了什么......
1 取自NumPy documentation "Data type objects"
内置Python类型
当用于生成dtype对象时,有几种python类型等效于相应的数组标量:
int np.int_ bool np.bool_ float np.float_ complex np.cfloat bytes np.bytes_ str np.bytes_ (Python2) or np.unicode_ (Python3) unicode np.unicode_ buffer np.void (all others) np.object_
答案 1 :(得分:7)
np.int_
是默认的整数类型(as defined in the NumPy docs),在64位系统上,这将是C long
。 np.intc
是C int
或int32
的默认int64
。 np.int
是内置int
函数
>>> np.int(2.4)
2
>>> np.int is int # object id equality
True
cython数据类型应该反映C
个数据类型,因此cdef int a
是C int
,依此类推。
至于np.int_t
,即Cython
编译时间等效于NumPy np.int_
数据类型,np.int64_t
是等效于{{1}的Cython
编译时间}}