###### tags: `Python`
# 串接比較運算
Python 有許多便利的語法, 不過如果沒有了解其中的細節, 就可能會出現意外的結果, 像是串接[比較運算](https://docs.python.org/3/reference/expressions.html#comparisons)就是一個例子。
## 兩個比較一次寫完
如果你想比較 `a` 是否介於 1~6 之間, 一般的寫法會是這樣:
```python
>>> a = 3
>>> a >=1 and a <=6
True
>>>
```
在 Python 中可以把 2 個比較運算串接在一起, 寫成這樣:
```python
>>> 1 <= a <= 6
True
>>>
```
它實際上就是:
```python
>>> 1 <= a and a <= 6
True
>>>
```
## 串接的比較運算只會計算運算元一次
雖然剛剛說串接的比較運算就等於拆開的兩個比較運算分別運算後再進行 `and` 運算, 但實際上**兩個比較運算器 (operator) 共用的運算元只會計算一次**, 請看以下範例:
```python
>>> a = [1, 2, 3]
>>> 1 <= a.pop() <= 6
True
>>> a
[1, 2]
```
由於中間的 `a.pop()` 只會執行一次, 並用其運算結果進行比較運算, 所以等同於:
```python
>>> 1 <= 3 <= 6
```
而比較運算結束後也可以看到 `a` 串列只彈出了 3 這個項目, 這跟以下的寫法是不一樣的:
```python
>>> a
[1, 2]
>>> 1 <= a.pop() and a.pop() <= 6
True
>>> a
[]
>>>
```
這種寫法在 `and` 左右兩側都執行了 `a.pop()`, 所以彈出了 2 個項目, 因此運算結束後, `a` 已經空掉了。
## 串接的比較運算彼此並不相關
不過在串接比較運算的時候, 千萬不要誤會, 串接的比較運算個別是獨立的, 彼此並不相關, 例如:
```python
>>> a = 10
>>> 5 < a > 8
True
>>>
```
實際上就是:
```python
>>> 5 < a and a > 8
True
>>>
```
跟 5 與 8 之間的比較完全無關, 就是兩個獨立分開的比較運算。即使是不同類型的比較, 也可以串接在一起, 例如:
```python
>>> a = 10
>>> b = [1, 2, 10]
>>> 2 < a in b
True
>>>
```
實際上就是:
```python
>>> 2 < a and a in b
True
>>>
```
## 你可以無限串接比較運算
依據上述原則, 其實你還可以無限串接, 像是這樣:
```python
>>> 1 < 10 > 8 < 8.2 > 3
True
>>>
```
只要記得 2 個比較運算器共用的運算元只會計算一次, 個別的比較運算器會取兩側的運算元進行運算, 並將結果 `and` 後就是串接比較運算的結果。
由於是 `and` 運算, 所以也遵循[布林運算的規則](https://docs.python.org/3/reference/expressions.html#boolean-operations), 只要目前的比較運算得到 `False`, 就不會進行後續的比較運算, 例如:
```python
>>> a = [1, 2, 3]
>>> 1 > 10 > a.pop()
False
>>> a
[1, 2, 3]
>>>
```
由於 `1 > 10` 已經是 `False`, 沒有必要進行 `10 > a.pop()` 的比較, 所以不會執行 `a.pop()`, 因此運算結束後 `a` 串列的內容不變。
要特別留意的是如果同樣的運算元出現多次, 就有可能計算該運算元多次, 例如:
```python
>>> a = [1, 2, 3]
>>> 1 < a.pop() > 2 > a.pop()
False
>>> a
[1]
>>>
```
由於 `1 < a.pop() > 2` 為 `True`, 所以會進行 `2 > a.pop()` 的比較運算, `a.pop()` 又執行了一次, 實際上就彈出了 2 個項目, 因此 `a` 串列內僅剩下 1 個項目。
## 小結
本文介紹的雖然是個小主題, 不過如果能夠善用, 就可以更簡潔清楚地表達複雜的比較運算, 值得花點時間學下來喔!