本書分四部分, 基于代碼實踐從各個角度來告訴大家如何編寫面向未來的Python代碼, 以及如何優(yōu)雅、合理地實現(xiàn)代碼的健壯性。第一部分講解Python中的類型和類型檢查器, 以及它們?nèi)绾螏椭_發(fā)人員在早期捕獲缺陷。第二部分重點關注如何創(chuàng)建自己的類型, 深入討論了枚舉類、數(shù)據(jù)類和類, 并探討了在設計類型時做出某些設計選擇來增加或降低代碼的健壯性。第三部分重點關注如何使開發(fā)人員能夠輕松地更改你的代碼, 討論了可擴展性、依賴項和架構模式等。第四部分探討如何構建安全網(wǎng), 以讓你擁有一個強大的、健壯的系統(tǒng); 該部分介紹各種有助于你捕捉惡意行為的靜態(tài)分析和測試工具。
本書適用于任何希望以可持續(xù)和可維護的方式開發(fā)代碼的Python開發(fā)人員。
注意,這并不是您的第1本Python書;閱讀本書前您應該熟悉Python控制流,并且以前使用過類。
如果:你正在尋找更具入門性的圖書,建議先閱讀Mark Lutz(O'Reilly)的《Learning Python》(中文版:《Python學習手冊》)
本書將研究用戶定義的類型,例如類和枚舉,以及Python的類型提示系統(tǒng)。還將探討如何使Python可擴展,以及如何使用一個全面的測試策略作為安全網(wǎng)。讀完本書你將能夠使用Python類型編寫更清晰、更易于維護的代碼。
主要內(nèi)容:
第1部分“為代碼添加類型注解”。介紹類型檢查如何在保證健壯性的工作中扮演重要角色。
第2部分“定義你自己的類型”。用面向?qū)ο蟮乃季S增加代碼的健壯性。
第3部分“可擴展的Python”。借助一些設計思想和常見架構,進一步提升代碼質(zhì)量。
第4部分“構建安全網(wǎng)”。用靜態(tài)檢查和測試完善整個代碼的安全網(wǎng)。
讀者得以從四個不同的角度了解各種Python技巧,并借助其中的例子加強“編寫良好代碼”(不只是Python)的意識。
希望閱讀此書的讀者都能有所收獲,并能夠?qū)⑵渲幸恍┳龇ɑ蛘咚枷霊玫阶约旱穆殬I(yè)生涯或者編碼工作中。
譯者序
編寫好代碼
“如何編寫一段好代碼?”我經(jīng)常被問到這樣的問題。寫了這么多年代碼,我心中仍然沒有一個標準答案。但是,我清楚地知道,什么樣的代碼是被人詬病的“爛代碼”:只能自己看懂甚至過段時間自己都看不懂的命名,牽一發(fā)而毀全身的神秘邏輯,讀起來就像行走于盜夢空間一樣的各種嵌套,等等。它們的產(chǎn)生一般都有一個共同原因:習慣著眼于現(xiàn)在而非未來。實現(xiàn)眼前的功能是大部分開發(fā)工作的第一要務,但是面向未來的思考往往能成就好的代碼。
在職業(yè)生涯中,我接觸過不少編程語言,回顧這些經(jīng)歷和經(jīng)驗,我發(fā)現(xiàn)語言或者工具并不是影響項目成功的關鍵,關鍵更在于開發(fā)者的意識。
意識,包含編碼習慣、設計風格、基于未來的思考等,這些都深刻影響著一段代碼的命運。這段代碼可能平淡無奇,可能被人贊嘆,也可能遭人唾棄。但是沒錯,它的優(yōu)劣完全由創(chuàng)造者來掌握。本書雖然基于Python,卻道出了很多編碼過程中值得學習和應用的實踐。換句話說,它不是在教我們?nèi)绾斡肞ython完成一個功能,而是在分享做好一個復雜項目的經(jīng)驗。
Python的進退
“人生苦短,我用Python”這句活躍在各大Python社區(qū)的名言,道出了Python語言的地位。作為一門動態(tài)解釋性語言,Python簡潔、優(yōu)雅、容易上手,一直是眾多編程愛好者喜愛的編程語言之一。但是往往也是因為這些“優(yōu)點”,很多開發(fā)者都容易在Python的大型項目中“放飛自我”,如果我們僅僅關注利用Python提供的方便工具或者豐富的庫來快速實現(xiàn)功能,不注重代碼本身的質(zhì)量和可維護性,那么隨著時間的推移,這些本來寫起來順風順水的代碼在將來會□成一堆別人不想觸碰的“垃圾山”。這也是業(yè)界對Python詬病多的地方,因為它和其他同為強類型的語言(比如Java、C#)相比,缺乏了太多限制,這就讓它顯得更加脆弱,編寫小型的工具或者庫時可能表現(xiàn)不明顯,可一旦用于大型的工程項目,很多人都會望而卻步。這也是我們很難看到Python大規(guī)模應用到國內(nèi)很多企業(yè)和大型項目中的原因。
然而,這并不意味著Python不夠強大,換句話說,Python作為靈活的強類型語言也可以長久健壯地應用在大型復雜項目中。本書基于Python 3論證了這一觀點,并通過代碼實踐從各個角度來告訴大家如何編寫面向未來的Python代碼,以及如何優(yōu)雅、合理地實現(xiàn)代碼的健壯性。
關于本書內(nèi)容
本次非常有幸與三位同事周偉、凌銳、凌云一起翻譯本書。本書通過四個部分分享了如何編寫健壯Python代碼:
第一部分“為代碼添加類型注解”。介紹類型檢查如何在保證健壯性的工作中扮演重要角色。
第二部分“定義你自己的類型”。用面向?qū)ο蟮乃季S增加代碼的健壯性。
第三部分“可擴展的Python”。借助一些設計思想和常見架構,進一步提升代碼質(zhì)量。
第四部分“構建安全網(wǎng)”。用靜態(tài)檢查和測試完善整個代碼的安全網(wǎng)。
讀者得以從四個不同的角度了解各種Python技巧,并借助其中的例子加強“編寫良好代碼”(不只是Python)的意識。
作為一名接觸Python語言、OOP以及敏捷技術實踐多年的架構師及開發(fā)者,我個人也從中學到了很多Python的技巧。希望閱讀此書的讀者都能有所收獲,并能夠?qū)⑵渲幸恍┳龇ɑ蛘咚枷霊玫阶约旱穆殬I(yè)生涯或者編碼工作中。
Patrick Viafore在關鍵任務軟件領域有超過14年的工作經(jīng)驗,專業(yè)方向涉及雷電檢測、電信和操作系統(tǒng)。他通過開發(fā)管道和工具,將Ubuntu鏡像部署到公有云供應商,并通過Kudzera有限責任公司進行軟件咨詢和項目承包(他是這家公司的負責人)。他的目標是使計算機科學以及軟件工程主題對開發(fā)者社區(qū)來說更加容易理解。
第1章 健壯的Python簡介9
1.1 健壯性9
1.2 你的意圖是什么12
1.3 Python中的意圖示例18
1.3.1 集合18
1.3.2 迭代21
1.3.3 □□驚訝原則22
1.4 小結24
第一部分 為代碼添加類型注解
第2章 Python類型簡介27
2.1 類型中有什么27
2.1.1 機器表達27
2.1.2 語義表達29
2.2 類型系統(tǒng)32
2.2.1 強類型與弱類型32
2.2.2 動態(tài)類型與靜態(tài)類型33
2.2.3 鴨子類型34
2.3 小結36
第3章 類型注解37
3.1 什么是類型注解37
3.2 類型注解的好處41
3.2.1 自動補全41
3.2.2 類型檢查器42
3.2.3 練習:找出bug43
3.3 什么時候使用類型注解45
3.4 小結46
第4章 約束類型47
4.1 Optional類型48
4.2 Union類型53
4.3 Literal類型57
4.4 Annotated類型58
4.5 NewType58
4.6 Final類型60
4.7 小結61
第5章 集合類型62
5.1 向集合添加類型注解62
5.2 同構集合與異構集合63
5.3 向字典添加類型67
5.4 創(chuàng)建新的集合類型69
5.4.1 泛型69
5.4.2 修改現(xiàn)有的類型71
5.4.3 像ABC一樣簡單74
5.5 小結76
第6章 自定義你的類型檢查器77
6.1 配置類型檢查器77
6.1.1 配置mypy78
6.1.2 mypy報告81
6.1.3 加速mypy82
6.2 其他類型檢查器83
6.2.1 Pyre83
6.2.2 Pyright88
6.3 小結90
第7章 采用類型檢查的實踐91
7.1 權衡利弊92
7.2 早日實現(xiàn)投入產(chǎn)出平衡93
7.2.1 找到你的痛點93
7.2.2 從戰(zhàn)略上選擇目標代碼94
7.2.3 依靠工具95
7.3 小結101
第二部分 定義你自己的類型
第8章 用戶自定義類型:枚舉105
8.1 用戶自定義類型105
8.2 枚舉106
8.2.1 Enum108
8.2.2 何時不使用109
8.3 高級用法109
8.3.1 自動分配值109
8.3.2 Flag111
8.3.3 整數(shù)轉(zhuǎn)換112
8.3.4 唯一性114
8.4 小結115
第9章 用戶自定義類型:數(shù)據(jù)類116
9.1 數(shù)據(jù)類實戰(zhàn)116
9.2 用法120
9.2.1 字符串轉(zhuǎn)換120
9.2.2 相等性121
9.2.3 關聯(lián)性比較121
9.2.4 不□性123
9.3 與其他類型的比較124
9.3.1 數(shù)據(jù)類與字典124
9.3.2 數(shù)據(jù)類與TypedDict125
9.3.3 數(shù)據(jù)類與命名元組125
9.4 小結126
第10章 用戶自定義類型:類127
10.1 類的剖析127
10.2 不□量129
10.2.1 避免損壞的不□量131
10.2.2 為什么不□量是有益的132
10.2.3 溝通不□量134
10.2.4 消費你的類134
10.2.5 維護者怎么辦136
10.3 封裝和維護不□量137
10.3.1 封裝137
10.3.2 保護數(shù)據(jù)訪問138
10.3.3 操作140
10.4 小結142
第11章 定義你的接口144
11.1 自然接口設計145
11.2 自然的交互148
11.2.1 自然接口實踐149
11.2.2 魔法方法153
11.2.3 上下文管理器155
11.3 小結158
第12章 子類型159
12.1 繼承159
12.2 可替代性163
12.3 設計方面的考慮168
12.4 小結171
第13章 協(xié)議172
13.1 類型系統(tǒng)之間的張力172
13.1.1 留空類型或使用Any類型174
13.1.2 使用Union174
13.1.3 使用繼承174
13.1.4 使用mixin176
13.2 協(xié)議177
13.3 高級用法179
13.3.1 復合協(xié)議179
13.3.2 運行時可檢查協(xié)議180
13.3.3 滿足協(xié)議的模塊180
13.4 小結181
第14章 使用pydantic進行運行時檢查183
14.1 動態(tài)配置183
14.2 pydantic189
14.2.1 驗證器190
14.2.2 驗證與解析193
14.3 小結194
第三部分 可擴展的Python
第15章 可擴展性197
15.1 可擴展性是什么197
15.2 開閉原則203
15.2.1 檢測OCP侵犯203
15.2.2 缺點204
15.3 小結205
第16章 依賴關系206
16.1 關系207
16.2 依賴關系的類型209
16.2.1 物理依賴關系209
16.2.2 邏輯依賴關系212
16.2.3 時間依賴關系213
16.3 可視化你的依賴關系215
16.3.1 可視化包215
16.3.2 可視化導入216
16.3.3 可視化函數(shù)調(diào)用217
16.3.4 解釋依賴關系圖219
16.4 小結220
第17章 可組合性221
17.1 可組合性介紹221
17.2 策略與機制225
17.3 較小規(guī)模的組合228
17.3.1 組合函數(shù)228
17.3.2 組合算法231
17.4 小結234
第18章 事件驅(qū)動的架構235
18.1 工作原理235
18.2 簡單的事件237
18.2.1 使用消息代理237
18.2.2 觀察者模式239
18.3 事件流241
18.4 小結243
第19章 可插入的Python245
19.1 模板方法模式246
19.2 策略模式248
19.3 插件式架構250
19.4 小結253
第四部分 構建安全網(wǎng)
第20章 靜態(tài)分析257
20.1 lint檢測257
20.1.1 編寫自己的Pylint插件259
20.1.2 分解插件261
20.2 其他靜態(tài)分析器263
20.2.1 復雜度檢查器264
20.2.2 安全分析266
20.3 小結267
第21章 測試策略268
21.1 定義測試策略268
21.2 降低測試成本273
21.3 小結282
第22章 驗收測試283
22.1 行為驅(qū)動開發(fā)284
22.1.1 Gherkin語言284
22.1.2 可執(zhí)行規(guī)范286
22.2 額外的behave特性288
22.2.1 參數(shù)化步驟288
22.2.2 表格驅(qū)動的需求288
22.2.3 步驟匹配289
22.2.4 定制測試生命周期289
22.2.5 使用標記選擇性地運行測試290
22.2.6 報告生成290
22.3 小結292
第23章 基于屬性的測試293
23.1 用Hypothesis開展基于屬性的測試293
23.1.1 Hypothesis的魔力297
23.1.2 與傳統(tǒng)測試的對比298
23.2 充分利用Hypothesis299
23.2.1 Hypothesis策略299
23.2.2 生成算法300
23.3 小結303
第24章 突□測試305
24.1 什么是突□測試305
24.2 用mutmut進行突□測試307
24.2.1 修復突□體309
24.2.2 突□測試報告310
24.3 采用突□測試311
24.4 小結314
*“時人不識凌云木, 直待凌云始道高!边@些保證/增強代碼健壯性的做法往往在一開始并不會彰顯它的魅力,但只要你堅持做正確的事情,它的作用和影響便一定會在日后慢慢凸顯。
“不積跬步,無以至千里!毕M蠹也粌H在編程過程中能夠保持追求完美、持續(xù)改進的習慣,而且在自己的學習生活過程中同樣能夠如此。從日常中積累,從細微處成長,早日實現(xiàn)自己工作和生活中的每一個目標。與君共勉!
姚文杰,凱捷咨詢數(shù)字化團隊架構師
*市場上介紹Python編程的書籍很多,許多開發(fā)人員只接觸了Python語言的表面,而沒有深入學習Python編程的所有工具和技巧。通過閱讀本書,你將學會如何更好地使用Python,你將接觸許多使得Python整潔并可維護的方法。這樣,未來的維護者也將會喜愛并使用你寫出的每段代碼,因為它是預先“精心設計”的。本書不只是編程的參考書,更是便于與公司和組織內(nèi)的開發(fā)人員一起探討如何好地應用這些編程原則的指南。
周偉凱捷咨詢數(shù)字化團隊資深項目經(jīng)理
*我們都知道Python是一門語法簡單、設計優(yōu)雅的語言,“低門檻”和“易用”這兩個特點造就了它活躍的生態(tài),進而使它擁有了大量庫和語法糖,并成為編程零基礎選手快速入門的不二之選。但與此同時,作為Python語言的使用者和軟件交付咨詢師,我深知我們不能因為手里有把好的砍柴刀就對危機四伏的軟件世界掉以輕心甚至洋洋得意。軟件工程所要應對的根本問題并不會憑空消失,很慶幸有Patrick Viafore這樣務實的技術作者能深入淺出地給軟件從業(yè)者分享寫出好代碼的原則、方法與工具,因此本書也同樣適用于使用其他編程語言的讀者。
梁凌銳
凱捷咨詢數(shù)字化團隊敏捷咨詢顧問
*Python是一門簡單易學并且功能非常強大的編程語言,所以即使你是編程新手,也可以通過自學很快上手。但是隨著軟件系統(tǒng)□得越來越復雜,僅僅接觸Python的表面是遠遠不夠的,否則軟件系統(tǒng)會因為膨脹而□得脆弱。因此,深入學習編寫健壯的Python代碼所需的所有工具和技巧是非常重要的。本書適用于有一定Python編程經(jīng)驗的讀者,涵蓋許多高級Python特性,但目的不僅僅是讓讀者會使用這些特性,而是基于這些特性去討論你的選擇會對代碼的可維護性產(chǎn)生哪些影響。
楊凌云
凱捷咨詢北方測試團隊負責人