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
结合场景再看三个关注点
- PATCH 语义靠
is None而不是真值。 - 库存 0 是合法值,不能当缺失。
- 空列表为假但仍是列表对象。
核心概念与准确模型
假值(常见)
None、False、0、0.0、0j、""、b""、空容器、自定义 __bool__/__len__ 返回假。
None
- 单例:
None is None - 类型
NoneType - 常作默认参数哨兵:
arg=None再内部分支
边界情况与反直觉行为
- 自定义类可通过
__bool__定义真值。 or链返回操作数:"" or "default"。- NumPy 数组真值可能抛歧义错误——库边界小心。
常见误区
[!warning] 常见误区:
if not xs等同“xs 是 None” 错误理解:假值就是缺失。
正确模型:缺失用is None;空集合是另一种业务状态。
工程实践
- 公共 API 用
Optional/X | None标注。 - 三态字段在文档写清。
- 配置项区分“未设置”与“设置为空字符串”。
本节总结
None 与真值是两层概念。业务分支先问“是否缺失”,再问“是否为空/为零”。
自测题
- 为什么清空昵称不能写成
if nickname:才更新? - 为什么检测 None 推荐
is?
参考答案
- 空串为假,会被当成“不更新”,无法清空。
- None 是单例;
is比身份,也避免__eq__干扰。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Truth Value Testing | 文档 | 真值规则 |
| None | 文档 | 常量 |