《Effective Python:編寫高質量Python代碼的59個有效方法》讀書筆記(完結)

Effective Python

第1章 用Pythonic方式來思考

  • be pythonicpython

  • 遵照pep8算法

  • python3有兩種字符序列類型:bytes(原始的字節)和str(Unicode字符).安全

  • 在python3中須要用二進制方式讀寫文件時,要用wb和rb數據結構

  • 應該儘量使用if/else表達式和輔助函數來使代碼清晰多線程

  • 不要在單次切片中同時指定start, end和stride.能夠採用兩步進行範圍切割和步進切割.閉包

  • 使用列表推導來代替map和filter併發

  • 不要在列表推導中使用兩個以上的表達式.使用if和for語句代替.ide

  • 若是數據量很大,用生成器表達式來改寫列表推導.生成器表達式會返回一個迭代器,而後能夠用next來生成新值.函數

  • 若是須要同時使用list的索引和元素,最好使用enumerate替代range性能

  • 用zip函數同時遍歷2個迭代器

  • 利用try/except/else/finally進行異常處理

第2章 函數

  • 儘可能用異常來表示特殊狀況,而不是None

  • python支持閉包,閉包是一種定義在某個做用域的函數,這種函數引用了那個做用域裏的變量.

  • python的函數是一級對象,也就是能夠直接引用,能夠賦給變量,能夠當成參數傳給其餘函數.

  • 函數中的局部變量不會影響外部做用域.若是須要獲取閉包函數內的數據,應該使用nonlocal聲明變量.若是使用nonlocal讓代碼變得複雜,應該將相關的函數封裝成輔助類.

  • 若是函數返回列表,能夠考慮用生成器改寫,將return變爲yield.

  • 若是須要在函數中屢次迭代一個生成器,能夠考慮把寫一個容器,把__iter__方法實現爲生成器.

  • 令函數接受可選的位置參數*args,可以使代碼清晰.若是要把列表中的全部元素做爲位置參數傳入,就在列表前加上*.

  • 可選參數有兩個問題,一個是過長的生成器做爲參數會致使消耗大量內存,一個是不方便修改函數.

  • 能夠用關鍵字參數表示函數可選的行爲和默認值.參數的默認值會在模塊加載的時候求出.所以不要在參數默認值中建立[]或{}等動態的值.解決方法是把默認值設爲None,並在docstring中具體解釋.

  • 能夠在定義函數的時候用*來分隔位置參數和關鍵字參數(只能以關鍵字指定的參數)

第3章 類與繼承

  • 當數據結構比較複雜時,儘可能用輔助類來維護程序的狀態,而不要用字典和元組.

  • 相似sort的key參數能夠接受一個函數,這稱掛鉤(hook)函數.

  • 簡單的接口應該接受函數而不是類的實例,由於函數是一級對象.

  • 若是要用函數保存狀態,應該定義新的類並實現__call__方法

  • 經過@classmethod能夠構造多態的類的對象.

  • 較複雜的繼承體系中,若是仍讓子類直接調用父類的__init__,會出現不少意想不到的行爲,所以建議用super初始化父類.

  • mix-iin是一種只定義了其餘類可能須要提供的一套附加方法的小型類.只在使用mix-in組件類時進行多重繼承.

  • Python類的屬性只有public和private.通常還會用單個下劃線開頭來習慣性命名protected.

  • private屬性是開頭至少有兩個下劃線,結尾至多有一個下劃線的屬性.python對於__private_name的保存機制其實是_ClassName__private_name.所以能夠經過這種方式訪問全部private屬性.

  • 應該多用前者,少用後者.

  • 若是要定製簡單子類,能夠直接從python的容器類型繼承.不然能夠繼承collections.abc中的抽象基類以實現自定義的容器類型.

第4章 元類及屬性

  • 用純屬性取代get和set方法

  • 若是想要使用get和set,應該使用@property修飾器的getter和setter.它的缺點是不便於複用.

  • 描述符能夠把同一套邏輯運用在類中的不一樣屬性上面.

  • WeakKeyDictionary能夠保證描述符類不會泄露內存

第5章 併發及並行

  • 併發(concurrency)是指計算機經過迅速切換看似在同一時間作不少不一樣的事.並行(parallelism)則是指計算機確實在同一時間作不少不一樣的事.

  • subprocess用於與外部進程交互.

  • Python解釋器能平行地運行多條子進程.

  • GIL確保了字節碼解釋器的協調性,但也帶來了同一時刻只能進行一條線程的負面影響.所以Python的多線程適用於處理阻塞式的I/O操做,而不是平行計算.

  • Python多線程一樣須要使用Lock來防止數據競爭,由於解釋器可能會在線程的任意時刻暫停它們.

  • 用queue.QUeue來協調各線程之間的工做.它解決了併發式管道存在的問題.

  • 線程存在的問題是:代碼複雜,須要佔用大量內存(大約8mb),啓動時的開銷比較大.協程能夠避免這些問題.

  • 協程的工做原理是:每當生成器函數執行到yield表達式時,消耗生成器的那段代碼,就經過send方法給生成器回傳一個值.

  • concurrent.futures會以子進程的形式平行地運行多個解釋器,從而令python可以利用多核心CPU來提高速度.這種作法適用於較爲孤立且數據利用率高的任務.

第6章 內置模塊

  • functools.wraps能夠定義函數修飾器,用於在函數執行以前以及執行完畢以後分別運行一些附加代碼.能夠實現約束語義,調試程序,註冊函數等目標.

  • contextlib模塊可使本身編寫的對象和函數支持with語句.

  • python的pickle模塊能將python對象序列化爲字節流,也能將這些字節反序列化爲python對象.可是這種序列化數據採用的是不安全的格式,若是其中有惡意信息,在反序列化時可能對程序形成損害.Json數據則是安全的.

  • copyreg能使pickle變得可靠.

  • 使用datetime而不是time來處理本地時間

  • 使用內置的算法和數據結構,例如collections.deque雙向隊列,collections.OrderedDict有序字典,collections.defaultdict帶有默認值的字典,heapq堆,bisect二分查找,itertools處理迭代器.

  • 在重視精確度的場合,應該使用decimal

第7章 協做開發

  • 爲每一個函數,類和模塊編寫docstring.

  • 用包來安排模塊,並提供穩固的API.

  • 爲自編的模塊定義根異常,以便將調用者與API相隔離.

第8章 部署

  • 能夠用模塊級別的代碼來配置不一樣的部署環境

  • 經過repr來輸出調試信息

  • 用unittest來測試代碼

  • pdb模塊的set_trace()可讓程序在執行到某一行的時候暫停,用於調試.

  • 利用cProfile來分析每一個模塊的性能,而後再優化.

  • 用tarcemalloc來掌握內存的使用及泄露狀況.

相關文章
相關標籤/搜索