# ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/98edff345fb44c9ca30237fa7958f6f8~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1920&h=1080&s=72 ...
1. 引子
def enabled() -> bool:
a = ["a,"b"]
b = True
c = False
return (b and c) or (b and a)
以上代碼返回什麼?
實際生產項目踩到的坑,也怪自己沒理解到未,才疏學淺!!!
想當然的以為 python 自己會做真值判斷了。其實真值判斷是在 if 條件語句時
會生效,但在普通的 and 的運算符下有另外一個規則。
2. python bool 類型簡述
“The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings ‘False’ or ‘True’ are returned, respectively.”
“布爾類型是整數類型的一個子類型,在幾乎所有的上下文環境中布爾值的行為類似於值0和1,例外的是當轉換為字元串時,會分別將字元串”False“或”True“返回。“
就python而言,True,1和1.0都表示相同的字典鍵
>>> True == 1 == 1.0
True
>>> (hash(True), hash(1), hash(1.0))
(1, 1, 1)
>>> issubclass(bool, int)
True
>>> isinstance(True, int)
True
>>> isinstance(False, int)
True
>>> int(True)
1
>>> int(False)
0
>>> help(bool)
Help on class bool in module builtins:
class bool(int)
| bool(x) -> bool
|
| Returns True when the argument x is true, False otherwise.
| The builtins True and False are the only two instances of the class bool.
| The class bool is a subclass of the class int, and cannot be subclassed.
3. bool類型之間的 and 運算
and 運算符有兩個操作數,可以是 bool,object,或一個組合
>>> True and True
True
>>> False and False
False
>>> True and False
False
>>> False and True
False
以上示例表明,僅當表達式中的兩個操作數都為 true 時,和表達式才返回 True。由於 and 運算符需要兩個操作數來構建表達式,因此它是一個二元運算符。
當兩邊操作書都為 bool 類型時,二元操作運算結果如下。
operand1 | operand2 | operand1 and operand2 |
---|---|---|
True | True | True |
True | False | False |
False | False | False |
False | True | False |
當然,以上的結果也適用於兩邊操作數一個 bool 表達式的情況。
expression1 and expression2
>>> 5>3 and 5==3+2
True
4. 不同類型之間的 and 運算
可以使用 and 運算符在單個表達式中組合兩個 Python 對象。在這種情況下,Python 使用內部的bool()
來判斷操作數的真值。此時,兩個對象之間的運算,結果將獲得一個特定的對象,而不是布爾值。僅當給定操作數顯式計算為 True 或 False 時,才會獲得 True 或 False
>>> 2 and 3
3
>>> 5 and 0.0
0.0
>>> [] and 3
[]
>>> 0 and {}
0
>>> 1 and {}
{}
>>> False and ""
False
>>> True and ""
''
>>> ["a"] and [1]
[1]
根據以上測試用例結果,當and運算結果為 False 時返回左操作數,當and運算結果為 True 時返回右操作數
關於真值的判斷規則,在 python 的文檔中有說明
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below.
By default, an object is considered true unless its class defines either a bool() method that returns False or a len() method that returns zero, when called with the object. 1 Here are most of the built-in objects considered false:
- constants defined to be false: None and False
- zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
- empty sequences and collections: '', (), [], {}, set(), range(0)
https://docs.python.org/3/library/stdtypes.html#truth-value-testing
以下是對象之間的比較結果集
object1 | object2 | object1 and object2 |
---|---|---|
False | False | object1 |
False | True | object1 |
True | True | object2 |
True | False | object2 |
綜上:如果 and 表達式中的操作數是對象而不是布爾表達式,則運算符在計算結果為 False 時返回左側的對象。否則,它將返回右側的對象,即使其計算最終結果為 False。
⚠️:如果在做對象邏輯運算,最終結果想得到 bool 類型 True/False的話,可以使用內建函數 bool(expression) 將結果重新實例化一下在返回
5. 高效運算-“快速短路”(short-circuit operator)
短路操作器,聽這個名字就知道是快速運算,Python 的邏輯運算符,如 and and or,使用稱為短路求值或惰性求值的東西來加速運算,高效得到結果。
例子:為了確認 and 表達式的最終結果,首先計算左操作數,如果它是False,那麼整個表達式都是False。在這種情況下,無需計算右側的操作數,就已經知道最終結果了
>>> def true_func():
... print("Running true_func()")
... return True
...
>>> def false_func():
... print("Running false_func()")
... return False
...
>>> true_func() and false_func() # Case 1
Running true_func()
Running false_func()
False
>>> false_func() and true_func() # Case 2
Running false_func()
False
>>> false_func() and false_func() # Case 3
Running false_func()
False
>>> true_func() and true_func() # Case 4
Running true_func()
Running true_func()
True
短路操作器,是提升代碼性能的一種有效手段。在邏輯運算表達式時,可考慮如下兩個原則:
- 將耗時的表達式放在 and 關鍵字的右側。這樣,如果短路規則生效,則不會運行代價高昂的表達式。
- 將更有可能為 false 的表達式放在 and 關鍵字的左側。這樣, 更有可能通過僅計算左操作數來確定整個表達式是否為 false。
當然,如果一定要執行運算符兩邊的表達式,則可以使用位運算符號 (&, |, ~),替代邏輯運算符
>>> def true_func():
... print("Running true_func()")
... return True
...
>>> def false_func():
... print("Running false_func()")
... return False
...
>>> # Use logical and
>>> false_func() and true_func()
Running false_func()
False
>>> # Use bitwise and
>>> false_func() & true_func()
Running false_func()
Running true_func()
False
6. bool 邏輯運算的萬能公式
Operation | Result | Notes | |
---|---|---|---|
法則 1 | x or y | if x is true, then x, else y | 1 |
法則 2 | x and y | if x is false, then x, else y | 2 |
法則 3 | not x | if x is false, then True, else False | 3 |
Notes:
- This is a short-circuit operator, so it only evaluates the second argument if the first one is false.
- This is a short-circuit operator, so it only evaluates the second argument if the first one is true.
- not has a lower priority than non-Boolean operators, so not a == b is interpreted as not (a == b), and a == not b is a syntax error.
多複雜的組合表達式,最終都可以一重重拆解成一個個獨立的小單元,在做合併
就拿開頭的引子來說
def enabled() -> bool:
a = ["a,"b"]
b = True
c = False
return (b and c) or (b and a)
拆成三步來看
- b and c --> 運用法則 2 (
if x is false, then x, else y
) 所以結果是 c 即 False - b and a --> a 運用法則 2 (
if x is false, then x, else y
) 所以結果是 a 即["a", "b"]
- False or ["a", "b"] 運用法則 1 (
if x is true, then x, else y
) 所以結果是 ["a", "b"]