产业气象站|为什么能支持任意的真值判断?,Python
文章图片
作者:豌豆花下猫
来源:Python猫
Python在涉及真值判断(TruthValueTesting)时 , 语法很简便 。
比如 , 在判断某个对象是否不为None时 , 或者判断容器对象是否不为空时 , 并不需要显示地写出判断条件 , 只需要在if或while关键字后面直接写上该对象即可 。
下图以列表为例 , ifmy_list这个简短的写法可以表达出两层意思:
文章图片
如果需要作出相反的判断 , 即“如果为None或为空” , 只需要写成ifnotmy_list即可 。
与众不同的真值判断方式通常而言 , 当一个值本身是布尔类型时 , 写成"ifxxx"(如果真) , 在语义上就很好理解 。 如果xxx本身不是布尔类型时 , 写成“ifxxx”(如果某东西) , 则在语义上并不好理解 。
在C/C++/Java之类的静态语言中 , 通常要先基于xxx作一个比较操作 , 比如“if(xxx==null)” , 以此得到一个布尔类型的值的结果 , 然后再进行真值判断 。 否则的话 , 若“ifxxx”中有非布尔类型的值 , 则会报类型错误 。
Python这门动态语言在这种场景中表现出了一种灵活性 , 那么 , 我们的问题来了:为什么Python不需要先做一次比较操作 , 直接就能对任意对象作真值判断呢?
先来看看文档中对真值判断的描述:
文章图片
简单而言 , Python的任何对象都可以用在if或while或布尔操作(and、or、not)中 , 默认情况下认为它是true , 除非它有__bool__()方法返回False或者有__len__()方法返回0 。
对于前面的例子 , my_list没有__bool__()方法 , 但是它有__len__()方法 , 所以它是否为true , 取决于这个方法的返回值 。
——真值判断的字节码
接着 , 我们继续刨根问底:Python为什么可以支持如此宽泛的真值判断呢?在执行ifxxx这样的语句时 , 它到底在做些什么?
对于第一个问题 , Python有个内置的bool()类型 , 可以将任意对象转化成布尔值 。 那么 , 这是否意味着Python在进行真值判断时 , 会隐式地调用bool()呢(即转化成ifbool(xxx))?(答案为否 , 下文有分析)
对于第二个问题 , 可以先用dis模块来查看下:
文章图片
POP_JUMP_IF_FALSE指令对应的是if语句那行 , 它的含义是:
IfTOSisfalse,setsthebytecodecountertotarget.TOSispopped.
如果栈顶元素为false , 则跳转到目标位置 。
这里只有跳转动作的描述 , 仍看不到一个普通对象是如何变成布尔对象的 。
Python在解释器中到底是如何实现真值判断的呢?
——真值判断的源码实现
在微信群友Jo的帮助下 , 我找到了CPython的源码(文件:ceval.c、object.c):
文章图片
文章图片
可以看出 , 对于布尔类型的对象(即Py_True和Py_False) , 代码会进入到快速处理的分支;而对于其它对象 , 则会用PyObject_IsTrue()计算出一个int类型的值 。
PyObject_IsTrue()函数在计算过程中 , 依次会获取nb_bool、mp_length和sq_length的值 , 对应的应该就是__bool__()和__len__()这两个魔术方法的返回值 。
这个过程就是前文中所引用的官方文档的描述 , 正是我们想要找的答案!
推荐阅读
- 帅气的烨烨|为什么600年来无人敢盗, 连孙殿英都怕?,明孝陵至今保存完好,
- 毒蛇|“冰火蛇”是什么来头?为什么它会被认为是地球上毒性最强的蛇?
- 腾讯微博|既然网盘生意那么烧钱,为什么阿里迅雷还要和百度网盘抢饭碗?
- 白宫|火星有生命吗?为什么探测器拍到形似“发动机”、“士兵”等物体
- 道达网络货运平台|为什么连互联网巨头都想加入网络货运?
- 移动支付|为什么全国加油站将停用微信支付?这其中有什么用意呢?
- 帝释天|为什么世界各地的神话竟然惊人地相似?也许宙斯跟帝释天是同一人
- 辉常观察|产业互联网:区块链与数字货币的分水岭,原创
- 点点雨落山岚|马化腾也表示无奈:为什么你们都将QQ号卖了?原来能换套房子
- 精选热点资讯|服务江西产业发展,晏斌:围绕直播大赛