← [ BACK_TO_NOTES ]

Python None 与真值判定

None 表示缺失;布尔上下文中的真值规则与“空容器/0/空串”陷阱;业务上如何区分未提供与空值。

#concept #growing #dev #python #python

[!info] related notes

Python None 与真值判定

这个概念为什么出现

API 字段经常出现三种状态:没传、传了空、传了有效值。若一律用 if value:,会把 0、""、[] 与 None 混成一种“假”,造成业务误判。

[!abstract] 一句话理解 None 是单例缺失标记,用 is None 判断;布尔上下文有独立真值规则,空容器与 0 为假,不等于“是 None”。

最小可运行示例

先把示例放进业务场景,再看代码:

场景:用户资料更新区分“清空昵称”与“未修改昵称”

本例约定 nickname=None 表示不改,空串表示清空;这只是函数契约,不是 PATCH 通用规则。若 HTTP 字段需要区分“未传”和显式 null,解析层必须保留键是否存在(或专用哨兵/框架字段集合),不能都转换成 None。

# profile_none_truth.py
# 业务意图:正确解释可选字段的三种状态。
# 教学点:
# - is None vs 真值测试;
# - 0 与 [] 为假但不是 None;
# - 业务分支应显式。

def apply_nickname(current: str, nickname: str | None) -> str:
    if nickname is None:
        return current  # 未提供:保持
    return nickname     # 提供了(含空串):覆盖


def can_ship(qty: int | None) -> str:
    if qty is None:
        return "missing qty"
    if qty <= 0:  # 负数为真,但也不能发货;业务范围需独立检查
        return "qty nonpositive blocked"
    return f"ship {qty}"


def main() -> None:
    print(apply_nickname("old", None))
    print(apply_nickname("old", ""))
    print(can_ship(None))
    print(can_ship(0))
    print(can_ship(2))
    print("bool([]):", bool([]), "[] is None:", [] is None)


if __name__ == "__main__":
    main()

建议运行:

python profile_none_truth.py

期望输出:

old

missing qty
qty nonpositive blocked
ship 2
bool([]): False [] is None: False

结合场景再看三个关注点

  1. is None 只区分 None 与非 None;未传、显式 null 和空串的业务映射要由 API 契约指定。
  2. 库存 0 是合法值,不能当缺失。
  3. 空列表为假但仍是列表对象。

核心概念与准确模型

假值(常见)

常见假值包括 None、False、数值零、空字符串/字节串及空容器。对象优先调用 __bool__(必须返回 bool),否则调用 __len__(返回非负整数,零为假);两者都未定义通常为真。真值测试也可能抛异常。

None

  • 单例:None is None
  • 类型 NoneType
  • 常作默认参数哨兵;若 None 本身是有效输入,要用另一个专用哨兵区分未提供。

边界情况与反直觉行为

  1. 自定义类可通过 __bool__ 定义真值。
  2. or 链返回操作数:"" or "default"。
  3. NumPy 数组真值可能抛歧义错误——库边界小心。

常见误区

[!warning] 常见误区:if not xs 等同“xs 是 None” 错误理解:假值就是缺失。
正确模型:缺失用 is None;空集合是另一种业务状态。

工程实践

  • Optional[X] / X | None 表示允许 None,不表示参数可省略;是否可省略由默认值决定,也不会自动执行运行时校验。
  • 三态字段在文档写清。
  • 配置项区分“未设置”与“设置为空字符串”。

本节总结

None 与真值是两层概念。业务分支先问“是否缺失”,再问“是否为空/为零”。

自测题

  1. 为什么清空昵称不能写成 if nickname: 才更新?
  2. 为什么检测 None 推荐 is?
参考答案
  1. 空串为假,会被当成“不更新”,无法清空。
  2. None 是单例;is 比身份,也避免 __eq__ 干扰。

延伸阅读与资料来源

资料类型支撑内容
Truth Value Testing文档真值规则
None文档常量
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本