---
title: Python 常用技巧
dates: 2020-12-15
tags:
- programming
- python
---
# Python 技巧筆記
## 常見錯誤
* 函式呼叫時,**Python 會暫存參數當前的值**,而 C++ 不會,試著比較以下程式碼。
```cpp
#include <algorithm>
#include <iostream>
int x = 12;
int func() {
x += 1;
return -100;
}
int main() {
std::cout << std::max(x, func()) << std::endl; // 13
}
```
```python
x = 12
def func():
global x
x += 1
return -100
print(max(x, func())) # 12
```
* 要不就是拿變數存 **`func()`** 結果再比較。
* 要不就是把 **`x`** 放後面。
* **溢位檢查**,假設皆為正數。
```python
# 相加
if a > INT_MAX - b: print('a + b overflows')
# 相減
if -a < INT_MIN - b: print('-(a + b) overflows')
# 相乘
if a > INT_MAX / b: print('a * b overflows')
```
同樣概念,取平均值也不應該直接相加除以二。
```python
mid = low + (high - low) // 2
```
## 常用技巧
* 在 Python 的 **`(), [], {}`** 當中的換行都會被忽略,善用~
```python
if (COND1 and
COND2 and
COND3):
```
### Sequences
* Listcomps 執行效率並不輸於 **`map`** 和 **`filter`**,善用~
```python
beyond_ascii = [ord(char) for char in s if ord(s) > 127]
beyond_ascii = [list(filter(lambda char: char > 127, map(ord, s)))]
```
* Genexp 相對節省記憶體,因為值是透過 iterator protocol 一個一個被產生,善用~
* **`tuple(... for ...)`** 這叫作 generator expressions (*genexpr*)
* **`[... for ...]`** 這才叫作 list comprehension (*listcomp*)
* **`{chr(i) for ...}`** 這叫作 set comprehension (*setcomp*)
* **`{k: v for ...}`** 這叫作 dict comprehension (*dictcomp*)
* 善用 **`min|max|sort|sorted`** 中的 **`key=`**
```python
# sort by values
{k:v for k, v in sorted(DICT.items(), key=lambda item: item[1])}
# sort by multiple factors
LIST.sort(key=lambda item: (item[0], item[1], -len(item)))
# min by string length
MIN_STR = min(STRs, key=len)
```
#### **`zip()`**
* **`list(zip(*m))`** 轉置二維陣列。
* 二維陣列取 column。
```python
list(zip(*m))[i]
[row[i] for row in m]
```
:::warning
**`m[i][:]`** 同 **`m[:][i]`** 同 **`m[i]`** 為取 row。
:::
* 根據 arr2 的值排序 arr1。
```python
zip_obj = zip(arr2, arr1)
sorted(zip_obj)
arr2, arr1 = zip(*zip_obj)
```
### Strings
#### **`format`** & f-string
```python
print('"{:^10}""'.format('hahaha')) # 置中
# " hahaha "
print('"{:<10.4}"'.format('hahaha')) # 置左
# "haha "
print('"{:>10.2f}"'.format(math.e)) # 置右
# " 2.72"
```
```python
# Python 3.6 or above
print(f'"{"hahaha":^10}"')
print(f'"{"hahaha":<10.4}"')
print(f'"{math.e:>10.2f}"')
```
#### 移除字元
```python
# 移除單一字元
s.replace(' ', '')
''.join(s.split(' '))
# 移除多個字元
''.join(re.split(' abc', s))
# 移除頭尾多字元
s.strip(' abc')
```
<!-- 6 intentional blank lines -->