­

python布爾類型和邏輯運算

  • 2020 年 1 月 20 日
  • 筆記

布爾類型

python中True表示真,False表示假,它們是布爾類型:

>>> type(True)  <class 'bool'>

在python中,bool的True和False是數值1和0的字元串表示格式,實際上bool類型是int類型的一個子類

>>> bool.__bases__  (<class 'int'>,)

因為True/False是數值1和0的另一種表示方式,它們可以直接參与數值運算。

>>> True + 2  3  >>> False + 2 - 1  1

True/False的各種形式

雖然True代表1,False代表0。但實際上,python中的任何一個數據對象要麼是True,要麼是False,所以可以直接在布爾測試的表達式中使用,而並非一定要去大小比較、通過函數測試等等。比如:

if "a":  while 1:

可以通過bool()函數來測試數據對象、表達式是True還是False。例如:

>>> bool(0)  False  >>> bool(1)  True  >>> bool('a')  True  >>> bool('')  False

那麼,哪些類型的數據是True,哪些類型的數據是False?

  • 整數值0、浮點數值0.0等、空字元串都為假
  • None為假
  • 空數據對象都是假,比如[]{}()
    • 注意,元組的括弧和逗號的特殊性。例如(())(None)(1)這些都不是元組,而是單個數據對象,加上逗號才算是元組。所以,使用括弧包圍但卻不是元組的數據,如果它們是假,則整個返回假,而不是元組看上去不為空而返回真

以下是各種內置數據類型的一些真、假示例:

          True                 False          ----------------------------------  number:   1、1.1               0、0.0  string:   'a'                  ''  None:                          None  list:     ['a']、[1]           []         [0]、['']、[None]  Set/Dict: {'a'}                {}  tuple:    ('a')、(1)           ()、('')、(0)、(None)

看幾個示例:

>>> bool(1), bool(0)  (True, False)    >>> bool('a'), bool('')  (True, False)    >>> bool(None)  False    >>> bool(['a']), bool([1]), bool([]), bool(['']), bool([()])  (True, True, False, True, True)    >>> bool({'a'}), bool({}), bool({''})  (True, False, True)    >>> bool(('a')), bool(()), bool(('')), bool((0)), bool(({}))  (True, False, False, False, False)    >>> bool(((),)),bool((None,))  (True, True)

實際上,一個數據對象是真還是假,是根據這個類型的__bool__()的返回值(為False則為假)以及__len__()的返回值(為0則為假)來決定的。

None

None為假,它不是表示對象為空,也不是表示對象未定義。它自身就是一個實實在在的數據對象,在記憶體中有自己的記憶體地址,而且整個python全局只有一個唯一的None對象。可以認為,None是一種特殊的數據對象,像數值1、字元串'a'一樣,只不過記憶體中這個數據對象裡面存儲的數據是我們不得而知的,但它永遠表示為False

>>> a = None  >>> b = None  >>> a is b  True

在Python中,沒有顯式定義return語句的函數、方法並不意味著沒有返回值,它們的默認返回值是None。比如print()函數:

>>> a=print("aa")  aa  >>> print(a)  None

None有時候有些小技巧。比如,訪問或設置超出列表長度的元素時會報錯:

>>> S = []  >>> S[1]  Traceback (most recent call last):    File "<stdin>", line 1, in <module>  IndexError: list index out of range  >>> S[1] = 2  Traceback (most recent call last):    File "<stdin>", line 1, in <module>  IndexError: list assignment index out of range

但是可以預先將某些數量的None對象填充到列表中去,這樣列表就具備了元素,儘管它們都是None對象。

例如,向列表中填充10個None元素:

>>> S = [None] * 10  >>> S  [None, None, None, None, None, None, None, None, None, None]  >>> S[1]  >>> S[1] = 2  >>> S  [None, 2, None, None, None, None, None, None, None, None]

當然,將None換成其它數據也一樣可以,比如0,但用None來填充,一看就知道是為了填充而填充的佔位符,不是實際要操作的元素。

另外,預先填充並不能限制列表的長度,可以繼續向這個列表中append()新元素。

邏輯運算:and、or、not

python中只支援字元形式的and、or、not邏輯運算,不支援符號類型的&&、||、!

  • X and Y:X和Y都為真時,返回真
  • X or Y:X或Y為真,返回真
  • not X:X真假取反
    • not優先順序很低,所以not a == b等價於not (a == b)

需要注意,and和or會短路運算(即只要能確定真假關係,就立即停止運算),並返回運算的結果(不是返回True/False,而是返回表達式的運算結果)。而not運算是返回True/False的。

例如,and的邏輯運算:

>>> 2 and 3, 3 and 2  (3, 2)  >>> [] and {}  []  >>> 3 and []  []

上面第一行and測試,因為and左邊的都是True,所以必須得評估and右邊的值,那麼不管and右邊是True還是False,都會返回and右邊的值,比如第一行and測試,第三行and測試。第二行and測試中,因為and左邊為False,所以直接能確定為False,所以直接短路返回[]

再看or邏輯運算:

>>> 2 or 3,3 or 2  (2, 3)  >>> [] or 3  3  >>> [] or {}  {}

上面第一行or測試,因為or左邊已經能直接確定為True,所以直接短路返回or左邊的值。第二行和第三行or測試,因為or左邊都為False,所以必須測試右邊的,所以不管or右邊是True還是False,都返回or右邊的值。

再次說明,and、or返回的不是True/False的布爾值,而是邏輯表達式的運算結果。但因為python中只要是數據,要麼是True,要麼是False,所以and/or/not都可以用於真假測試,只不過and/or還可以在布爾測試的基礎上進行賦值操作。

例如,如果變數a為False,就賦值為某個值,否則採用a原有的值。

a = a or "hhhh"

更通用的,變數A取X、Y、Z等表達式中的一個。

A = X or Y  A = X or Y or Z

不僅如此,and/or還能實現if中選擇值的功能。例如,下面是等價的:

A = (( X and Y) or Z)    if X:    A = Y  else:    A = Z

當然,這種用and/or實現邏輯的可讀性太差,能用if的當然用if。

空、非空測試的建議

經常會遇到要測試數據是否為空。這裡的空可能是None、""、[]、{}、()中的一種,建議不要使用len() == 0去測試:

if len(x) == 0:  if not len(x) == 0:

而是直接將數據作為真、假值進行判斷:

if x:  if not x: