今天来做个选择,notnotx和bool(x)哪个更好?它们都可以把x变成布尔值:>>>x=123>>>notnotxTrue>>>bool(x)True>>>那么谁更快呢?让我们写一段代码,运行100万次,比较谁更快:importtimeitdefbool_convert(x):returnbool(x)defnotnot_convert(x):returnnotnotxdefmain():trials=10_000_000kwargs={"setup":"x=42""globals":globals(),"number":trials,}notnot_time=timeit.timeit("notnot_convert(x)",**kwargs)bool_time=timeit。timeit("bool_convert(x)",**kwargs)print(f"{bool_time=:.04f}")print(f"{not_time=:.04f}")if__name__=="__main__":main()运行结果如下:其实bool(x)之所以慢是因为它是函数调用,notnotx是一条指令,有更快的路径转换为布尔值,可见来自字节码:bool(x)添加了LOAD_GLOBAL和CALL_FUNCTION。这里附一下相关字节码的官方说明:LOAD_GLOBAL(namei)Loadstheglobalnamedco_names[namei]ontothestack.CALL_FUNCTION(argc)Callsacallableobjectwithpositionalarguments.argcindicatesthenumberofpositionalarguments.Thetopofthestackcontainspositionalarguments,withtheright-mostargumentontop.Belowtheargumentsisacallableobjecttocall.CALL_FUNCTIONpopsallargumentsandthecallableobjectoffthestack,callsthecallableobjectwiththosearguments,andpushesthereturnvaluereturnedbythecallableobject.UNARY_NOTImplementsTOS=notTOS.最后从结果看了一下,notnotx比bool(x)快,主要原因是bool(x)是函数调用,函数调用需要把参数压入栈顶。堆栈的顶部包含位置参数,最右边的参数在顶部,参数Below是要调用的可调用对象。CALL_FUNCTION从堆栈中弹出所有参数和可调用对象,使用这些参数调用可调用对象,并压入可调用对象返回的返回值,这个过程比not指令慢得多。不过,我仍然建议您使用bool(x),因为它更具可读性,而且您不太可能调用它一百万次。
