python中not not x 與bool(x) 的區別

他們都可以把 x 變成一個佈爾類型的值:

>>> x = 123
>>> not not x
True
>>> bool(x)
True
>>>


那麼誰更快呢?我們寫段代碼,跑個 100 萬次,來比較下誰更快:

import timeit


def bool_convert(x):
    return bool(x)


def notnot_convert(x):
    return not not x


def main():
    trials = 10_000_000
    kwargs = {
        "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"{notnot_time = :.04f}")


if __name__ == "__main__":
    main()

運行結果如下:

其實 bool(x) 慢的原因在於它是一個函數調用,而 not not x 就是一條指令,具有更快捷的轉換為佈爾值的路徑,這一點可以從字節碼可以看出來:

bool(x) 多瞭 LOAD_GLOBAL CALL_FUNCTION

這裡附一下相關字節碼的官方說明:

LOAD_GLOBAL(namei)
Loads the global named co_names[namei] onto the stack.

CALL_FUNCTION(argc)
Calls a callable object with positional arguments. argc indicates the number of positional arguments. The top of the stack contains positional arguments, with the right-most argument on top. Below the arguments is a callable object to call. CALL_FUNCTION pops all arguments and the callable object off the stack, calls the callable object with those arguments, and pushes the return value returned by the callable object.

UNARY_NOT
Implements TOS = not TOS.


最後:

從結果來看,not not x 比 bool(x) 更快,主要原因在於 bool(x) 是一個函數調用,函數調用需要參數壓入棧頂,堆棧的頂部包含位置參數,最右邊的參數在頂部,參數下面是要調用的可調用對象。CALL_FUNCTION 從堆棧中彈出所有參數和可調用對象,使用這些參數調用可調用對象,並推送可調用對象返回的返回值,這一過程比一個 not 指令要慢得多。

不過我仍然推薦你使用 bool(x) ,因為它的可讀性更高,而且,我們也不太可能調用它 100萬次。

到此這篇關於pythonnot not x 與 bool(x) 的區別的文章就介紹到這瞭,更多相關not not x與bool(x) 的區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: