【Python】 bool()

今天開發的時候踩的一個坑,發現我的一個 flag 每次都是 true,後來才發現我掉的 bool() 的陷阱了 :crying_cat_face:

情境是這樣的我們用了一個全域變數給使用者傳值,當它使用 multi gpu 時傳入 1 否則傳入 0 ,用來作為判斷是否進行分散式訓練的前處理,按這個邏輯交出了這樣的程式碼:

1
2
3
import os

IS_MULTI_GPU = bool(os.environ.get("IS_MULTI_GPU",0))


但卻發現我這個 flag 每次都是 true,導致 flag 有設跟沒設是一樣 :expressionless:

bool()

這個函數最廣為人知的用法大概是:

1
2
3
4
5
bool(0)
>>> False

bool(1)
>>> True


但回頭去查文件發現 bool 其實是 int 的子類別。看到這句話,我大概知道我的判斷式哪邊出錯了,os.environ.get 取回來的是字串,而不是整數…

果然細看可以發現 bool() 只有在下列情況回傳 false 而已,其他狀況都是回傳 true:

  1. 傳入 False 值。
  2. 傳入 None。
  3. 傳入空值,如:空陣列、空列表、空字典、空字串…等。
  4. 傳入數字 0 ,資料型態為整數或浮點數都算。
  5. 傳入物件類別具有 __bool ____len()__,且其回傳值為 False0


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## case 1 : 傳入 False 值
bool(False)
>>> False

## case 2 : 傳入 None
bool(None)
>>> False

## case 3 : 傳入空值,如:空陣列、空列表、空字典、空字串...等
bool([])
>>> False

bool({})
>>> False

bool(())
>>> False

bool("")
>>> False

## case 4 : 傳入數字 0 ,資料型態為整數或浮點數都算。
bool(0.0)
>>> False

bool(0)
>>> False

## case 5 : 傳入物件類別具有 `__bool __` 或 `__len()__`,且其回傳值為 `False` 或 `0`
class Test():
  def __init__(self):
    pass

  def __bool__(self):
    return False

bool(Test())
>>> False


class Test2():
  def __init__(self):
    pass
         
  def __len__(self):
    return 0
         
bool(Test())
>>> False


而按照這規則 os.environ.get 取回來的是非空字串,所以這個 flag 每次都是 true…。既然知道哪邊出問題了,就好修正了…

1
2
3
import os

IS_MULTI_GPU = os.environ.get("MULTI_GPU", 0) == "1"


最後嚴格要求當輸入為字串 1 時,才會啟動這個 flag。

參考資料

  1. Chinmoy Lenka 。bool() in Python 。檢自 GeeksforGeeks (2020-02-27)。
  2. Python bool() 函数 。檢自 runoob (2020-02-27)。