Python 中的 None:理解空值、NoneType 与常见陷阱

2026-09-20 25 预计阅读时间: 1 分钟
来源: realpython.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:5 分钟

在 Python 里,None 承担了其他语言中 nullnil 的角色:它表示“没有值”,但并不等同于 0False、空字符串或空容器。理解 None 的身份、比较方式和默认参数行为,是读懂 Python 代码与 traceback 的基础。

先做一个小测验

下面哪些表达式的结果为 True

value = None

print(value is None)
print(value == None)
print(value is False)
print(value == 0)
print(type(value).__name__)

正确结果是:

True
True
False
False
NoneType

None 是一个单例对象,类型是 NoneType。因此,type(None) 的结果是 <class 'NoneType'>,而不是字符串或特殊的“空类型”。

判断 None 时使用 is None

推荐使用身份比较:

result = None

if result is None:
    print("没有返回结果")
else:
    print(f"结果是:{result}")

is 判断两个变量是否指向同一个对象,== 判断值是否相等。对于 None,Python 社区约定使用 is Noneis not None。这样表达意图更清晰,也避免自定义对象重载 __eq__ 后产生意外行为。

不要把所有“假值”都当成 None

values = [None, False, 0, "", [], {}]

for value in values:
    print(repr(value), value is None, bool(value))

这里除了 None 以外,其他值也可能在条件判断中表现为假,但它们表达的含义不同。比如 0 是数值零,[] 是空列表,而不是“没有这个值”。

None 适合做默认参数吗?

当参数需要区分“调用者没有传值”和“调用者明确传入空容器”时,None 是很实用的默认值:

def collect_tags(tags=None):
    if tags is None:
        tags = []
    tags.append("python")
    return tags

print(collect_tags())
print(collect_tags([]))

输出:

['python']
['python']

不要直接把可变对象写成默认参数:

def unsafe_collect_tags(tags=[]):
    tags.append("python")
    return tags

print(unsafe_collect_tags())
print(unsafe_collect_tags())

两次调用可能得到同一个持续增长的列表,因为默认参数对象会在函数定义时创建,并在多次调用之间复用。使用 None 作为哨兵值,再在函数体中创建新列表,可以避免这种状态泄漏。

None 如何出现在 traceback 中

函数没有显式写 return 时,会隐式返回 None

def find_user(user_id):
    if user_id == 1:
        return {"id": 1, "name": "Ada"}
    # 没有匹配时隐式返回 None

user = find_user(2)
print(user)  # None

如果后续代码把这个返回值当成字典使用,就可能出现类似错误:

user = find_user(2)
print(user["name"])

典型 traceback 会提示:TypeError: 'NoneType' object is not subscriptable。这句话的关键不是“NoneType 很特殊”,而是变量当前的值为 None,代码却尝试执行只有字典、列表等对象才支持的下标操作。

可以在使用前显式处理:

user = find_user(2)

if user is None:
    print("用户不存在")
else:
    print(user["name"])

实践检查清单

  • None 表示缺失、尚未计算或没有结果。
  • 判断空值时优先写 value is Nonevalue is not None
  • 不要把 NoneFalse0"" 和空容器混为一谈。
  • 对列表、字典等可变默认参数使用 None,并在函数体内初始化。
  • 看到 NoneType traceback 时,沿调用链检查哪个函数返回了 None,以及调用者是否正确处理了它。

None 看成一个明确的状态,而不是一个可以随意替换所有空值的占位符,代码的接口和错误处理都会更可靠。


相关推荐