python|Python 为什么能支持任意的真值判断?( 二 )
PyObject_IsTrue() 函数在计算过程中 , 依次会获取 nb_bool、mp_length 和 sq_length 的值 , 对应的应该就是 __bool__() 和 __len__() 这两个魔术方法的返回值 。
这个过程就是前文中所引用的官方文档的描述 , 正是我们想要找的答案!
另外 , 对于内置的 bool() , 它的核心实现逻辑正是上面的 PyObject_IsTrue() 函数 , 源码如下(boolobject.c):
本文插图
所以 , Python 在对普通对象作真值判断时 , 并没有隐式地调用 bool() , 相反它调用了一个独立的函数(PyObject_IsTrue()) , 而这个函数又被 bool() 所使用 。
也就是说 , bool() 与 if/while 语句对普通对象的真值判断 , 事实上是基本相同的处理逻辑 。 知道了原理 , 就会明白if bool(xxx) 这种写法是多此一举的了(我曾见到过) 。
至此 , 我们已经回答了前文中提出的问题 。
——验证真值判断的过程
接下来 , 有 3 个测试例子 , 可以作进一步的验证:
本文插图
你可以暂停而思考下:bool(Test1) 与 bool(Test1()) 各是什么结果?然后依次判断剩下的两个类 , 结果又会是什么?
揭晓答案:
bool(Test1) # Truebool(Test2) # Truebool(Test3) # Truebool(Test1()) # Truebool(Test2()) # Falsebool(Test3()) # True
原因如下:
- 类对象没被实例化时 , bool() 不会调用它的 __bool__() 或 __len__() 这两个魔术方法
- 类对象被实例化后 , 若同时存在 __bool__() 或 __len__() 魔术方法 , 则 bool() 会先调用 __bool__() 方法(PS:这个方法要求返回值必须为 bool 类型 , 因此只要有它 , 就必然不需要再用__len__() 方法来判断真假)
除了这 3 个例子 , 还有一种情况值得验证 , 那就是对于数字类型 , 它们是怎么做真值判断的呢?
我们可以验证一下数字类型是否拥有那两个魔术方法:
hasattr(2020, "__bool__")hasattr(2020, "__len__")
不难验证出 , 数字拥有的是 __bool__() 魔术方法 , 并没有__len__() 魔术方法 , 而且所有类型的数字其实被分成了两类:
- __bool__() 返回 False:所有表示 0 的数字 , 例如0, 0.0, 0j, Decimal(0), Fraction(0, 1)
- __bool__() 返回 True:所有其它非 0 的数字
Python 中if xxx 这种简便的写法 , 虽然是正规的真值判断语法 , 并它但并不符合常规的语义 。 在 C/C++/Java 之类的语言中 , 要么 xxx 本身是布尔类型的值 , 要么是一种可返回布尔类型值的操作 , 但是在 Python 中 , 这个“xxx”竟然还可以是任意的 Python 对象!
本文通过对文档、字节码和 CPython 解释器的源码逐步分析 , 发现了 Python 的真值判断过程并不简单 , 可以提炼出以下的几个要点:
- if/while 是隐性的布尔操作符: 它们除了有“判断”真假的作用 , 还具有隐式地将普通对象计算出布尔结果的功能 。 实际的操作是解释器根据“POP_JUMP_IF_FALSE”指令来完成的 , 其核心逻辑跟内置的 bool() 是共用了一个底层方法
- 真值判断过程依赖两个魔术方法: 除非被判断对象有__bool__() 方法返回False 或者有__len__() 方法返回0, 否则布尔操作的结果都是 True 。 两个魔术方法总是会先计算__bool__()
- 数字类型也可做真值判断: 数字有__bool__() 魔术方法 , 但没有__len__() 魔术方法 , 除了表示 0 的数字为 False , 其它数字都为 True 。
推荐阅读
- 温枪|为什么测温枪一下子就能测出人体的温度?
- 中年|Python编程语言有什么独特的优势呢?
- 科学|为什么没有人被暗物质杀死?
- |为什么微信用户这么多,QQ还能成为中国第二大社交软件?
- 设备|投屏功能为什么如此重要
- 科学|为什么动物能直接喝脏水,而人类喝水需要过滤?
- 凤凰网|投屏功能为什么如此重要
- 群众网|为什么富人选择创业,穷人却选择打工?
- 群众网|马云的妻子张瑛有多优秀?为什么她不像刘强东妻子章泽天那样经常出现?
- |变声器为什么一定要有实时变声功能?能实现什么有趣的玩法?