空值 None
None 是 Python 中 NoneType 类型的唯一实例,用于表示"什么都没有"、"不存在"或"未设置"。它在函数返回值、默认参数和哨兵值等场景中扮演重要角色。
None 的本质
None 是单例对象,整个 Python 进程中只有一个 None 实例:
a = None
b = None
print(a is b) # True
print(type(a)) # <class 'NoneType'>
NoneType 不能创建新实例,也不能被继承:
# 以下均非法
# x = NoneType() # NameError/TypeError
# class MyNone(NoneType): pass # TypeError
None 与 False、0、"" 的区别
初学者常混淆这些"空"值,但它们含义不同:
print(None == False) # False
print(None == 0) # False
print(None == "") # False
print(bool(None)) # False,但 None 不是 False
在布尔上下文中它们都为假,但类型和语义截然不同:
| 值 | 类型 | 含义 |
|---|---|---|
None | NoneType | 不存在、未设置 |
False | bool | 逻辑假 |
0 | int | 数值零 |
"" | str | 空字符串 |
[] | list | 空列表 |
def check(value):
if value is None:
return "未设置"
if value == "":
return "空字符串"
if value == 0:
return "数值零"
if not value:
return "其他假值"
return "有值"
print(check(None)) # 未设置
print(check("")) # 空字符串
print(check(0)) # 数值零
print(check([])) # 其他假值
print(check("hello")) # 有值
用 is None 判断
判断一个值是否为 None,必须使用 is 运算符,而非 ==:
# 不推荐
if x == None:
pass
# 推荐
if x is None:
pass
# 同样推荐
if x is not None:
pass
原因有二:一是 None 是单例,is 比较身份更高效;二是某些类可能重载 __eq__ 使 == None 产生意外结果:
class Weird:
def __eq__(self, other):
return True
w = Weird()
print(w == None) # True,意外!
print(w is None) # False,正确
函数默认返回 None
如果函数没有显式 return 语句,或 return 后无值,则返回 None:
def greet(name):
print(f"Hello, {name}")
result = greet("world")
print(result) # None
这是设计上的选择:副作用型函数不需要返回值,调用者不应依赖其返回值做逻辑判断。
默认参数的陷阱
None 常用于避免可变默认参数的问题:
# 错误:默认参数在函数定义时求值,共享同一列表
def append_item_wrong(item, lst=[]):
lst.append(item)
return lst
print(append_item_wrong(1)) # [1]
print(append_item_wrong(2)) # [1, 2],意外!
# 正确:用 None 作为哨兵
def append_item_right(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
print(append_item_right(1)) # [1]
print(append_item_right(2)) # [2],正确
作为哨兵值
当 0、False、"" 都是合法数据时,None 是表示"未提供"的唯一选择:
def find_user(user_id, default=None):
if user_id < 0:
return default
return {"id": user_id, "name": "Alice"}
print(find_user(-1)) # None
print(find_user(-1, default=0)) # 0
边界情况
None 不支持任何运算:None + 1、None * 2、None[0]、len(None) 均抛出 TypeError。
None 在容器中的行为:
lst = [None, None, 1]
print(len(lst)) # 3,None 是合法元素
print(lst.count(None)) # 2
print() 的返回值:
result = print("hello")
print(result) # None,print 返回 None
None 是 Python 数据模型中表达"缺失"的标准方式。正确使用 is None 判断、避免与 False 混淆、利用它解决默认参数问题,是写出健壮代码的基本功。