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