Python None 与真值判定

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

#type / concept #status / growing #tech / dev #resource / python #tech / lang / python

[!info] 关联笔记

Python None 与真值判定

这个概念为什么出现

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

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

最小可运行示例

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

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

PATCH 接口:nickname is None 表示不改;nickname == "" 表示清空。

# 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 not qty:  # 0 为假
        return "qty zero 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 zero blocked
ship 2
bool([]): False [] is None: False

结合场景再看三个关注点

  1. PATCH 语义is None 而不是真值。
  2. 库存 0 是合法值,不能当缺失。
  3. 空列表为假但仍是列表对象。

核心概念与准确模型

假值(常见)

NoneFalse00.00j""b""、空容器、自定义 __bool__/__len__ 返回假。

None

  • 单例:None is None
  • 类型 NoneType
  • 常作默认参数哨兵:arg=None 再内部分支

边界情况与反直觉行为

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

常见误区

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

工程实践

  • 公共 API 用 Optional/X | None 标注。
  • 三态字段在文档写清。
  • 配置项区分“未设置”与“设置为空字符串”。

本节总结

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

自测题

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

延伸阅读与资料来源

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