Effective Python 筆記

目的

參考了 “Reading Great Code” 原本想要單刀直入的在Github上閱讀有關 python open source,要看之前卻不太知道怎麼下手。於是開始找尋其它人的做法。

根據 “我的原始碼閱讀之道” 和 “軟件開發者路線圖:從學徒到高手(譯本)” 二個參考資料的建議,都有提到Effective 系列的書,所以希望在看別人的源碼前先閱讀這本書並記錄出筆記。

effective python

[reference]
Reading Great Code
我的原始碼閱讀之道
軟件開發者路線圖:從學徒到高手(譯本)
effective python
effective python中文版


01. Know Which Version of Python You’re Using

* python2 發展上己經涷結,而 python3 不斷的發展,下個python 專案強烈建議用 python 3。

* python2 轉成 python 3 的工具有 2to3 和 six。


02. Follow the PEP 8 Style Guide

* 遵守 PEP8 (Python Enhancement Proposal #8)風格,這份指南會一直被更新。

* 「The Zen of Python states: “There should be one—and preferably only one—obvious way to do it.” 」(應該只有一個也是偏好的唯一一個,達成目標的明顯做法)。

[reference]
PEP 0008 – Style Guide for Python Code


03. Know the Differences Between bytes, str, and unicode

基礎觀念:

* 純文字文件,不過是編輯器讀取檔案的二進位資料,嘗試對照某個編碼之後,再繪製出對應的字元外觀給你看。(ref. 哪來的純文字檔?)

1
二進位的位元組(Byte)(ex.0100 1010) -> 16進位來顯示(ex. 4A) -> ASCII表 -> A

*Unicode 一開頭的兩個位元組(ff fe)是用來識別檔案採用的位元組順序,稱為BOM(byte order mark),之後使用兩個位元組(固定)來儲存每個Unicode字元。 (ref. Unicode 與 UTF)

* Unicode的實作方式之一 UTF-8(8-bit Unicode Transformation Format),使用可變長度位元組的方式來儲存字元,一個字元的儲存長度可從一個位元組到四個位元組(ref. UTF-8)

* python2 是以 ASCII 編碼 來解讀原始碼,所以若沒有打上Encoding declaration 宣告原始碼為 UTF-8 來編碼,打中文就會發生錯誤。

* python2 中 strunicode 可表示字元序列(sequences of characters)。

1
2
3
python2
|__ str: raw 8-bit values
|__ unicode: Unicode

* python3 中 bytes 與 str 可表示字元序列(sequences of characters)

1
2
3
python3
|__ bytes: raw 8-bit values
|__ str: Unicode

* python3 中的 str 實體與 Python2 中的 unicode 實體所用的二進位編碼方式並沒有關聯(原因是?)。

* Unicode 字元 -> 二進位資料 encode
* 二進位資料 -> Unicode 字元 decode

* python3 bytes 和 str 永遠都不會相等 (原因是?)
* python2 str 若是 7-bit ASCII 那 unicode 與 str 實體就一樣,還可一起運算。

[reference]
哪來的純文字檔?
Unicode 與 UTF
UTF-8


04. Write Helper Functions Instead of Complex Expressions

*python語法很容易讓你寫出太複雜難讀的 single-line expressions。

*將複雜 expressions 移到 helper functions, 特別是你需重復使用相同的logic。

*用 if else expr ession 代替 or 和 and 可讓你更好讀。

1
red = int(my_value.get('red', [''])[0] or 0)

改為下面的方式會比較好讀

1
2
3
4
5
red = int(my_value.get('red', [''])
if red[0]:
red = int(red[0])
else
red = 0

更可以寫成 helper function

1
2
3
4
5
6
7
8
9
def get_first_int(values, key, default=0)
found = values.get(key, [''])
if found[0]:
found = int(found[0])
else:
found = default
return found

red = get_first_int(my_values, 'red')