真值判断
(Truth Value Testing)时,语法很简便。if my_list
这个简短的写法可以表达出两层意思:if not my_list
即可。静态语言
中,通常要先基于 xxx 作一个比较操作,比如“if (xxx == null)”,以此得到一个布尔类型的值的结果,然后再进行真值判断。否则的话,若“if xxx”中有非布尔类型的值,则会报类型错误。动态语言
在这种场景中表现出了一种灵活性,那么,我们的问题来了:为什么 Python 不需要先做一次比较操作,直接就能对任意对象作真值判断呢?False
或者有__len__() 方法返回0
。if xxx
这样的语句时,它到底在做些什么?隐式地
调用 bool() 呢(即转化成if bool(xxx)
)?(答案为否,下文有分析)dis
模块来查看下:POP_JUMP_IF_FALSE
指令对应的是 if 语句那行,它的含义是:If TOS is false, sets the bytecode counter to target. TOS is popped.
如果栈顶元素为 false,则跳转到目标位置。
if bool(xxx)
这种写法是多此一举的了(我曾见到过)。bool(Test1)
与 bool(Test1())
各是什么结果?然后依次判断剩下的两个类,结果又会是什么?bool(Test1) # True
bool(Test2) # True
bool(Test3) # True
bool(Test1()) # True
bool(Test2()) # False
bool(Test3()) # True
hasattr(2020, "__bool__")
hasattr(2020, "__len__")
__bool__()
返回 False:所有表示 0 的数字,例如0
, 0.0
, 0j
, Decimal(0)
, Fraction(0, 1)
__bool__()
返回 True:所有其它非 0 的数字if xxx
这种简便的写法,虽然是正规的真值判断语法,并它但并不符合常规的语义。在 C/C++/Java 之类的语言中,要么 xxx 本身是布尔类型的值,要么是一种可返回布尔类型值的操作,但是在 Python 中,这个“xxx”竟然还可以是任意的 Python 对象!False
或者有__len__() 方法返回0
,否则布尔操作的结果都是 True。两个魔术方法总是会先计算__bool__()