bool 是 int 的子类,因为其继承关系在源码中明确定义:issubclass(bool, int) 和 isinstance(true, int) 均为 true;但 type(true) 是 bool 而非 int,故 type(true) is int 为 false。

因为 bool 在 Python 的类型系统中就是 int 的子类,不是“看起来像”,而是 CPython 源码里明确定义的继承关系:issubclass(bool, int) 返回 True,isinstance(True, int) 也返回 True。
为什么 type(True) is int 是 False?
这是最容易混淆的点:类型检查严格区分“实际类型”和“继承关系”。True 的类型是 bool,所以 type(True) is int 为 False;但它确实是 int 的实例,因此 isinstance(True, int) 为 True。这就像你儿子姓你,但他不叫“你”——继承了父类行为,但有自己的身份。
-
type(True)→<class></class> -
isinstance(True, int)→True -
True + 1→2(合法,无隐式转换) -
[10, 20][False]→10(因为False == 0,且支持整数索引)
bool 只有两个值,但为什么还能参与所有整数运算?
因为 bool 复用了 int 的底层表示和方法,但封死了构造任意值的路径。它不是“只有两个整数”,而是“只有两个合法的 bool 实例”:
-
bool(2)→True(非零转True,不生成新bool值) -
bool(0)→False -
True.__add__(True)→2(调用的是int.__add__) -
'%d' % True→'1'(格式化走int路径)
注意:bool 类重写了 __repr__ 和 __str__,所以打印时显示 True/False,但数值行为完全由 int 支撑。
哪些场景下这个设计会出问题?
语义上“真/假”和数值“1/0”混用,在松散上下文中没问题,但在强类型约束环境里容易踩坑:
-
numpy.array([True, False], dtype=int)→array([1, 0])(类型被抹平) -
json.dumps({'flag': True})→'{"flag": true}'(JSON 没布尔类型,但序列化后类型信息丢失) - Django ORM 字段定义为
BooleanField,传入1可能被接受,但传入True才符合语义预期 -
if x == 1:和if x is True:行为完全不同——前者匹配所有值为 1 的对象(包括int、float等),后者只匹配True实例
真正要警惕的不是“能不能算”,而是“该不该用数值含义替代布尔语义”。比如用 True * 100 替代条件分支,代码可读性会迅速崩坏;在类型敏感场景(如 API schema、数据库字段校验),显式转换或类型注解比依赖继承关系更可靠。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











