--- 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 -->