news 2026/10/25 2:31:09

别再让 NaN 和 None 把你搞晕了:谈谈 Python 里的“空值”哲学

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再让 NaN 和 None 把你搞晕了:谈谈 Python 里的“空值”哲学

搞数据处理或者写后端接口的朋友,大概率都经历过这种“鬼打墙”的时刻:

数据库里明明是NULL,读到 Python 里变成了None,扔进 Pandas 做个计算变成了NaN,最后想转成 JSON 返回给前端时,因为包含NaN直接报错,或者变成了一个前端 JS 无法识别的NaN符号。

最近读了 Filip Mularczyk 的一篇名为《Nothing to Declare》的文章,很有共鸣。特别是在 Pandas 3.0 普及的当下,我们处理“没有值”这种状态时,依然容易掉坑里。

今天就来聊聊这三个长得像、但脾气完全不同的“空值”:NaN、None和null,以及如何在工程中优雅地处理它们。

三个“空”,三种命

首先得祛魅,这三位在 Python 的内存里完全是三个物种:

  1. None (Python 的亲儿子)

    • 它是 Python 的内置对象,属于NoneType。
    • 它代表**“逻辑上的无”**。比如“用户没有填昵称”,这就是None。
    • 它是一个单例(Singleton),用来做判断时,永远要用is None而不是== None。
  2. NaN (数学界的怪胎)

    • 全称 Not a Number,但它在 Python 里居然是float类型!
    • 它代表**“数值上的缺失或计算错误”**。比如0/0或者读取了一个空的 CSV 数值格。
    • 它最反直觉的地方在于“六亲不认”:NaN != NaN是成立的。这意味着你没法用==去在列表里找它,必须用math.isnan()或pd.isna()。
  3. null (外来的和尚)

    • Python 语法里没有null。
    • 它通常存在于JSON或SQL中。
    • 当我们谈论null时,通常是在讨论数据交换(IO)。当一个 JSON 的null传进来,Python 的json库默认把它转成None。

工程实践中的“灾难现场”

Filip 在文章里提到了一个非常典型的场景:使用 Pydantic 做数据校验。

假设前端给你发来这样一个 JSON:

{"temperature":null,"humidity":"NaN"}

如果你在 Pydantic 模型里定义字段为float,事情就变得微妙了。

  • 对于null:Pydantic 默认可能抛错,除非你声明类型为float | None(或者Optional[float])。
  • 对于"NaN":Pydantic 会很“贴心”地把它转成 Python 的float('nan')。

问题来了:当你把这个清洗后的模型存入数据库,或者做数学运算时,混入的None和NaN会导致完全不同的结果。None可能会让数学运算抛出 TypeError,而NaN会像病毒一样,让所有跟它运算的结果都变成NaN。

怎么处理才优雅?

结合文章观点和现在的工程习惯,我有几个建议:

1. 语义分离:是“没填”还是“算错了”?

在定义数据模型(Model)时,要明确区分这两种状态。

  • 如果是因为用户没填,或者数据暂缺,尽量保持为None。
  • 如果是传感器读数错误、计算溢出,保留NaN是合理的,因为它保留了“这是一个数值类型”的特征。
2. 利用 Pydantic 的 Validator

不要指望自动转换能完全符合心意。在 Pydantic 中,最好写个field_validator(v2 写法):

# 伪代码示例:确保导出时行为可控@field_validator('score')@classmethoddefhandle_empty_score(cls,v):ifvisNone:returnfloat('nan')# 如果业务要求必须是数值计算returnv

或者反过来,在序列化成 JSON 之前,把所有的NaN清洗回None,因为标准的 JSON 规范其实并不支持NaN(虽然有些解析器能容忍),传null给前端通常是最安全的做法。

3. Pandas 3.0 的新常态

现在是 2026 年,Pandas 3.0 已经让Nullable类型(如Float64、Int64,注意是大写首字母)成为了主流。

以前最让人头大的问题是:一个整数列里混进一个NaN,整列会被强制强转成浮点数。现在,推荐使用 PyArrow 后端或者 Pandas 的 Nullable 类型。这允许None(在 Pandas 里表现为<NA>)和整数和平共处,而不需要动不动就退化成浮点型的NaN。

总结

并没有一种万能的“空值”能解决所有问题。

  • 做数学计算:请用NaN,并小心它的传染性。
  • 做逻辑流转:请用None。
  • 做接口交互:认准null,并确保在 Python 边界处(比如 Pydantic 层)把NaN和None的转换规则定死,别让它们“自由发挥”。

写代码时多想一步:“这个空,到底是因为不存在,还是因为算不出来?”这一秒的思考,能帮你省下好几个小时 debug 的时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/25 2:28:43

OpenHarmony环境下React Native:ImageBackground覆盖层布局

OpenHarmony环境下React Native&#xff1a;ImageBackground覆盖层布局 在现代移动应用界面设计中&#xff0c;背景图与覆盖层的结合是提升视觉冲击力与信息层级的重要手段。无论是在登录页、音乐播放器还是商品展示卡片中&#xff0c;我们经常需要在一张背景图片上叠加半透明…

作者头像 李华
网站建设 2026/10/25 2:29:45

把年会办成演唱会,追觅果然“敢梦敢为”

2月4日&#xff0c;苏州奥体中心体育场灯光璀璨&#xff0c;追觅科技与央视携手打造的“敢梦敢为追觅之夜”演唱会正式登场。这不仅是一次动人的视听盛宴&#xff0c;更是一份献给追觅全体员工的温暖心意。活动突破传统企业年会的活动形式&#xff0c;以央视级演唱会盛典&#…

作者头像 李华
网站建设 2026/10/25 2:29:44

无锡奥特维科技股份有限公司 软件工程师-机器人(W0202) 职位深度解析与面试指南

无锡奥特维科技股份有限公司 软件工程师-机器人(W0202) 职位信息 岗位职责: 1. 负责前期机器人仿真模拟,机器人路径模拟,规划设计机器人运动路线; 2. 负责项目机器人程序开发设计,根据工艺要求设计机器人动作、通讯程序; 3. 负责处理现场问题及优化,根据工程部现场反馈的…

作者头像 李华
网站建设 2026/10/25 2:30:56

从 C 基础到 ARM Linux 驱动开发:嵌入式开发核心知识点全解析

一、C 语言核心&#xff1a;嵌入式开发的语法基石 嵌入式开发以 C 语言为核心工具&#xff0c;指针、自定义类型、编译特性等知识点是直接操作硬件寄存器、编写高效程序的关键&#xff0c;以下为高频核心概念与实操要点&#xff1a; 1. 指针家族&#xff1a;地址操作的核心&a…

作者头像 李华
网站建设 2026/10/16 6:39:25

Linux常用命令大全:RMBG-2.0运维指南

Linux常用命令大全&#xff1a;RMBG-2.0运维指南 在实际运维RMBG-2.0背景去除服务的过程中&#xff0c;很多同学发现——模型跑起来了&#xff0c;但遇到问题时却不知道从哪下手。日志里一堆报错看不懂&#xff0c;进程突然没了找不到原因&#xff0c;GPU显存占满却查不出是哪…

作者头像 李华
网站建设 2026/10/21 13:28:32

深度解析ES6 Set与Map:相同点、核心差异及实战选型

深度解析ES6 Set与Map&#xff1a;相同点、核心差异及实战选型 ES6引入的Set和Map&#xff0c;是JavaScript中两种重要的“集合类型”&#xff0c;用于解决传统数组、对象在数据存储与查找中的痛点——比如数组去重繁琐、对象键名只能是字符串/ Symbol 类型。很多开发者在使用…

作者头像 李华