ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

NumPy Data Type Routines 全解:类型判定、提升与信息查询

NumPy Data Type Routines 全解:类型判定、提升与信息查询 NumPy Data Type Routines 全解类型判定、提升与信息查询【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy导读本文基于 NumPy 官方参考文档中的 Data type routines 章节系统讲解 NumPy 数据类型dtype例程的五大分类类型判定can_cast、类型提升promote_types/result_type/min_scalar_type/common_type、数据类型创建dtype/rec.format_parser、机器信息查询finfo/iinfo以及类型测试与杂项工具isdtype/issubdtype/typename/mintypecode。读完本文你将掌握每个例程的完整签名、参数语义、返回规则与典型用法并能结合仓库源码理解其底层实现位置与设计动机。一、Data type routines 总览NumPy 官方参考将 dtype 相关的例程分为五组本文按此骨架展开分类例程功能Data type routines类型例程can_cast、promote_types、min_scalar_type、result_type、common_type类型转换可行性判断与类型提升Creating data types创建类型dtype、rec.format_parser构造 dtype 对象、解析格式字符串Data type information类型信息finfo、iinfo浮点与整型的机器限制Data type testing类型测试isdtype、issubdtype判断类型归属与层次关系Miscellaneous杂项typename、mintypecode类型名描述与最小类型字符这些函数并非分散在不同模块从仓库源码看can_cast、min_scalar_type、result_type定义在 numpy/_core/multiarray.pyPython 分发层通过array_function_from_c_func_and_dispatcher包装_multiarray_umath中的 C 实现isdtype、issubdtype定义在 numpy/_core/numerictypes.pyfinfo、iinfo定义在 numpy/_core/getlimits.pytypename、mintypecode、common_type则位于 numpy/lib/_type_check_impl.py。理解这一布局有助于在需要深挖实现时快速定位代码。二、类型判定can_cast 与 casting 规则2.1 函数签名can_cast(from_, to, castingsafe)用于判断从类型from_转换到类型to是否符合给定的 casting 规则返回布尔值。其声明位于 numpy/_core/multiarray.py#L604参数含义from_源类型可以是 dtype、dtype 说明符、NumPy 标量或数组to目标类型dtype 或 dtype 说明符casting控制允许的转换种类取值如下casting 取值含义no完全不允许任何类型转换equiv仅允许字节序byte-order变化safe仅允许能保值的转换same_kind允许 safe 转换或同一种类内部的转换如 float64 → float32unsafe允许任意数据转换2.2 典型示例import numpy as np np.can_cast(np.int32, np.int64) # True保值的加宽转换 np.can_cast(np.float64, complex) # Truefloat64 → complex128 可保值 np.can_cast(complex, float) # False复数转浮点可能丢失虚部 np.can_cast(i8, f8) # Trueint64 → float64注意大整数可能有精度损失 np.can_cast(i8, f4) # Falseint64 → float32 不保证保值 np.can_cast(i4, S4) # False数值与字符串之间不能 safe 转换2.3 版本行为说明NumPy 2.0 起源码 docstring 明确标注了 2.0 的行为变化见 multiarray.py#L634-L636versionchanged:: 2.0该函数不再支持 Python 标量也不再对 0 维数组和 NumPy 标量应用任何基于值value-based的逻辑。也就是说在 NumPy 2.x 中can_cast的判断完全基于 dtype 本身而非传入的具体数值这是理解该函数现代语义的关键。三、类型提升promote_types、result_type、min_scalar_type、common_type3.1 promote_types两个类型的提升结果promote_types(type1, type2)返回对两个输入类型应用提升规则后得到的结果 dtype其类型签名__type1: DTypeLike, __type2: DTypeLike - dtype可参考 numpy/_core/multiarray.pyi#L2700底层实现位于_multiarray_umath扩展模块。它只接受两个操作数适合用于两个数组相运算的结果类型这类场景。np.promote_types(np.int8, np.uint16) # dtype(int32) np.promote_types(np.float32, np.int64) # dtype(float64)3.2 result_type任意多个操作数的提升结果result_type(*arrays_and_dtypes)接收任意数量的数组与 dtype返回应用 NumPy 类型提升规则见参考文档 arrays.promotion后的结果类型声明位于 multiarray.py#L714。它是promote_types的多操作数推广也是最贴近实际运算语义的提升查询工具np.result_type(3, np.arange(7, dtypenp.int8)) # dtype(int8)小标量不会抬高结果类型 np.result_type(np.int32, np.complex64) # dtype(complex128) np.result_type(3.0, -2) # dtype(float64)注意第一个例子Python 标量3与int8数组的结果仍是int8这是标量不提升结果类型规则的体现2.0 起不再有 value-based promotion。3.3 min_scalar_type容纳一个值的最小类型min_scalar_type(a)对标量a返回能容纳其值的最小尺寸、最小种类的 dtype对非标量数组则原样返回数组的 dtype。声明位于 multiarray.py#L666并有两条重要规则浮点数不会下沉为整数复数不会下沉为浮点数。np.min_scalar_type(10) # dtype(uint8) np.min_scalar_type(-260) # dtype(int16)负数需要带符号类型 np.min_scalar_type(3.1) # dtype(float16)浮点值保持浮点种类 np.min_scalar_type(1e50) # dtype(float64)超出 float16/float32 范围 np.min_scalar_type(np.arange(4, dtypenp.float64)) # dtype(float64)数组原样返回该函数常与result_type配合使用例如根据实际数值动态选择紧凑的存储 dtype。3.4 common_type数组的公共标量类型common_type(*arrays)位于 numpy/lib/_type_check_impl.py#L666返回输入数组的公共标量类型注意是标量类型np.float32这类 class而非 dtype。其规则与前述提升函数不同返回值永远是不精确inexact的浮点标量类型即使输入全是整型数组只要出现整型数组最小精度也是 64 位浮点float64除int64、uint64之外的所有输入都能无损转换为返回值。从实现看L702-L725它遍历数组整型统一映射到float64精度其余按array_precision表取最高精度只要任一输入是复数对象结果就落在复数分支。示例np.common_type(np.arange(2, dtypenp.float32)) # numpy.float32 np.common_type(np.arange(2, dtypenp.float32), np.arange(2)) # numpy.float64整型参与 → float64 np.common_type(np.arange(4), np.array([45, 6.j]), np.array([45.0])) # numpy.complex128需要强调common_type只接受数组输入。源码中若输入不是数组会抛出TypeError并明确提示对 dtype 或标量类型求公共类型请使用np.result_type或np.promote_types——这正是它与提升函数分工的边界。四、创建数据类型dtype 与 rec.format_parser4.1 dtype一切类型的入口dtype是 NumPy 中最核心的构造器接受类型对象、类型字符、字符串说明符、元组如(base, shape)子数组、字典含names/formats/offsets/titles/itemsize/aligned键等返回一个 dtype 实例。其关键属性包括kind种类字符如i、f、c、b、S、U、V、O、itemsize字节数与name。name属性的实现细节在 numpy/_core/_dtype.py#L338-L361 的_name_get中对于object与bool类型不附加位数后缀其他类型会追加itemsize * 8的位宽datetime 类型还会追加时间单元元数据如datetime64[ns]。这也是 NumPy 2.5 弃用numpy.typename、建议改用dtype.name的原因——后者给出的就是这种位名称。np.dtype(np.int32).name # int32 np.dtype(f8).name # float64 np.dtype(datetime64[ns]).name # datetime64[ns]4.2 rec.format_parser把格式串解析为结构化 dtyperec.format_parser是 numpy/_core/records.py#L57 中定义的类负责把格式、字段名、标题描述转换为结构化 dtype。构造完成后结果通过.dtype属性获取dtype np.rec.format_parser(formats, names, titles).dtype参数说明完整定义见 records.py#L70-L92formats格式描述可以是逗号分隔的字符串如f8, i4, S5也可以是格式字符串列表如[f8, i4, S5]names字段名逗号分隔字符串或字符串列表/元组传空列表时使用默认字段名(f0, f1, ...)titles标题字符串序列空列表表示不设置标题aligned可选默认False为True时按 C 编译器的方式填充对齐字段byteorder可选指定后所有字段统一改为该字节序可用说明符参见dtype.newbyteorder。 import numpy as np parser np.rec.format_parser([f8, i4], [col1, col2]) parser.dtype dtype({names: [col1, col2], formats: [f8, i4], titles: [col1, col2], offsets: [0, 8], itemsize: 16})五、数据类型信息finfo 与 iinfo5.1 finfo浮点类型的机器限制finfo(dtype)定义在 numpy/_core/getlimits.py#L52返回浮点或复数浮点类型的机器限制对象。它支持复数输入此时返回的是对应实部浮点类型的信息如np.finfo(np.complex64).dtype为float32。核心属性见 getlimits.py#L58-L110属性含义bits类型占用的位数dtype对应的 dtype复数输入返回其分量的浮点 dtypeeps1.0 与下一个更大可表示浮点数之差IEEE-754 双精度下为2**-52≈ 2.22e-16epsneg1.0 与下一个更小可表示浮点数之差双精度下为2**-53≈ 1.11e-16iexp/nexp指数部分位数 / 含符号与偏置的指数位数machep/negep产生eps/epsneg的指数max/min最大可表示数 / 最小可表示数通常为-maxmaxexp/minexp溢出对应指数C 标准 MAX_EXP/ 无前导 0 的最负指数MIN_EXP - 1nmant尾数显式位数不含规格化数的隐式前导位precision该浮点类型近似可精确表示的十进制位数resolution近似十进制分辨率即10**-precisiontinysmallest_normal的向后兼容别名smallest_normal最小的正规格化浮点数smallest_subnormal最小的正非规格化subnormal浮点数文档 Notes 还提醒开发者getlimits.py#L124-L129不要在模块顶层实例化finfo因为首次计算开销较大、会拖慢导入对象本身有缓存在函数内反复调用没有问题。np.finfo(np.float64).dtype # dtype(float64) np.finfo(np.complex64).dtype # dtype(float32) np.finfo(np.float32).eps # 1.1920929e-07 np.finfo(np.float64).max # 1.7976931348623157e308对longdouble其表示因平台而异多数平台是 IEEE-754 的 binary128四精度或 binary64-extended80 位扩展精度而 PowerPC 上可能是 IBM double-double 格式一对 float64精度与范围特性特殊见 getlimits.py#L137-L141。5.2 iinfo整型类型的机器限制iinfo(int_type)定义在 getlimits.py#L342返回整型类型的机器限制属性简洁bits、dtype、min、max。实现上L399-L434bits itemsize * 8无符号类型最小值为 0、最大值为(1 bits) - 1有符号类型最小值为-(1 (bits-1))、最大值为(1 (bits-1)) - 1输入非整型种类kind不是i或u时抛出ValueError。np.iinfo(np.int16).min # -32768 np.iinfo(np.int16).max # 32767 np.iinfo(np.uint8).max # 255 np.iinfo(np.int32(10)).min # -2147483648也接受标量实例六、数据类型测试isdtype 与 issubdtype6.1 issubdtype类型层次包含关系issubdtype(arg1, arg2)是内置issubclass在 dtype 上的对应物定义在 numpy/_core/numerictypes.py#L419。它沿 NumPy 的类型层次hierarchy判断arg1是否为arg2的子类型。类型层次全貌见该模块顶部的文档注释numerictypes.py#L40-L77generic - bool (kindb) - number | - integer | | - signedinteger (kindi) 如 byte/short/intc/intp/int_/longlong | | - unsignedinteger(kindu) 如 ubyte/ushort/uintc/uintp/uint/ulonglong | - inexact | - floating (kindf) 如 half/single/double/longdouble | - complexfloating (kindc) 如 csingle/cdouble/clongdouble - flexible | - character (bytes_ kindS / str_ kindU) | - void (kindV) - object_ (kindO)行为要点含 docstring 示例np.issubdtype(np.int32, np.integer) # True np.issubdtype(np.float32, np.integer) # False np.issubdtype(np.float32, np.floating)# True np.issubdtype(np.float64, np.float32) # False不同位宽互不为子类型 np.issubdtype(S1, np.bytes_) # Truedtype-like 对象也可用 np.issubdtype(i4, np.signedinteger) # True实现上L476-L481非generic子类的参数会被dtype(arg).type归一化为标量类型再做issubclass判断。6.2 isdtype按语义种类判断类型isdtype(dtype, kind)定义在 numerictypes.py#L329用于判断给定 dtype 是否属于指定的种类kind。目前仅支持 NumPy 内置 dtype第三方 dtype 尚不支持。kind参数可以是 dtype、字符串、或它们的元组合法的字符串种类为kind 字符串含义bool布尔类型signed integer有符号整型unsigned integer无符号整型integral整型有符号 无符号real floating实浮点类型complex floating复数浮点类型numeric数值类型整型 浮点 复数实现上L377-L415字符串种类会被展开为sctypes中的具体类型集合未知字符串抛出ValueError非 NumPy dtype 参数抛出TypeError。np.isdtype(np.float32, np.float64) # False具体 dtype 之间是精确匹配 np.isdtype(np.float32, real floating) # True np.isdtype(np.complex128, (real floating, complex floating)) # True元组取并集 np.isdtype(np.int32, integral) # True np.isdtype(np.uint8, signed integer) # False七、杂项typename 与 mintypecode7.1 mintypecode最小安全转换类型字符mintypecode(typechars, typesetGDFgdf, defaultd)定义在 numpy/lib/_type_check_impl.py#L27返回能安全容纳给定所有类型数据的最小尺寸类型的类型字符。typechars类型字符列表若传入 array_like则使用其dtype.chartypeset候选返回字符集合默认GDFgdf长双精度复数/双精度复数/单精度复数/长双精度/双精度/单精度default若typechars与typeset无交集时返回的默认字符默认d。实现上有特殊规则L71-L78若交集中同时出现F与d直接返回D因为单精度复数与双精度实数并存时必须提升到双精度复数否则按_typecodes_by_elsize的元素大小序取最小值。np.mintypecode([d, f, S]) # d np.mintypecode(np.array([1.1, 2-3.j])) # D复数输入 np.mintypecode(abceh, defaultG) # G无交集时返回默认值7.2 typename类型字符的描述文本已弃用typename(char)返回类型字符的人类可读描述定义于 _type_check_impl.py#L585。例如d→double precision、F→complex single precision、?→bool、S→string、V→void。注意该函数已在 NumPy 2.5 标记为弃用DeprecationWarning官方建议改用numpy.dtype.name见 L589-L590。原因正如 4.1 节 所述dtype.name通过 numpy/_core/_dtype.py 的_name_get直接给出位名称无需维护独立的字符映射表也更准确。八、实践要点与选型建议综合以上 API给出几个实用的选型准则问能不能转换→ 用can_cast务必理解casting五档no/equiv/safe/same_kind/unsafe的递进关系问运算结果是什么类型→ 用result_type多操作数或promote_types两操作数注意 NumPy 2.0 起标量不再影响结果类型想按实际值压缩存储→ 用min_scalar_type找出能容纳标量值的最小 dtype想统一一组数组的公共类型强制浮点→ 用common_type但要记住它只接受数组且结果恒为浮点/复数查询机器限制→ 浮点用finfo含eps、max、smallest_normal等全套属性整型用iinfomin/max/bits判断类型归属→ 沿类型层次判断用issubdtype按语义种类如real floating、integral判断用isdtype构造结构化 dtype→ 直接使用np.dtype或通过np.rec.format_parser从格式串批量解析字段。上述全部函数均由本仓库官方文档 routines.dtype.rst 收录每个函数在generated/下还有独立页面源码实现与类型层次图分别位于 multiarray.py、numerictypes.py、getlimits.py 与 lib/_type_check_impl.py可随时深入查阅以验证行为细节。【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进