Python之禪:編寫優(yōu)雅Python代碼的16個(gè)原則
↑↑↑點(diǎn)擊上方藍(lán)字,回復(fù)資料,10個(gè)G的驚喜
作者:劉宇宙,《Python進(jìn)階編程:編寫更高效 優(yōu)雅的Python代碼》一書作者。

假如你剛參與了一個(gè)算法項(xiàng)目,當(dāng)你第一次打開這個(gè)項(xiàng)目時(shí),發(fā)現(xiàn)里面已經(jīng)有上萬行與算法相關(guān)的代碼,仔細(xì)查看過后,發(fā)現(xiàn)如下一些讓你抓狂的問題:
1、代碼寫的非常冗余,維護(hù)已經(jīng)變得越來越困難。
2、幾乎沒有任何注釋。
3、非常錯(cuò)亂的代碼風(fēng)格,讓你有一種感覺打開了一個(gè)雜亂的網(wǎng)站的html頁面。
4、存在那么幾個(gè)函數(shù),單個(gè)函數(shù)的源碼超過500行。
5、每一次需求的變更,都意味著一次痛苦的代碼編寫。
這是筆者以前參與一個(gè)算法項(xiàng)目時(shí)遇到的問題。
在參與這個(gè)項(xiàng)目時(shí),大家都在很努力的使項(xiàng)目往期望的方向走,但隨著開發(fā)進(jìn)度的往前推進(jìn),項(xiàng)目的復(fù)雜性正在不斷加大,大家都在盡可能使用自己了解的最好的技術(shù)將系統(tǒng)打造的更為強(qiáng)壯,但系統(tǒng)但復(fù)雜性一點(diǎn)也沒有降低。在需求但不斷變化中,代碼的冗余也越來越明顯。程序中到處充斥著廢棄的代碼,但誰也不敢輕易去刪除,誰也不清楚自己的一個(gè)不經(jīng)意操作,是否會(huì)導(dǎo)致整個(gè)程序的奔潰。
對(duì)于代碼的開發(fā),里面包含了很多細(xì)枝末節(jié)的東西,特別對(duì)于需要高度配合的項(xiàng)目(如算法人員和工程人員之間),細(xì)節(jié)的處理是否妥當(dāng),將很大程度影響項(xiàng)目是否可以成功交付,跨行之間的配合與細(xì)節(jié)的處理是大部分開發(fā)者所欠缺的,這類人才也是市場(chǎng)上急需的。
python的設(shè)計(jì)宗旨是簡(jiǎn)單、優(yōu)雅、明確。
但很多開發(fā)人員通過自己的努力將其做成了復(fù)雜、丑陋、晦澀。
結(jié)合Python之禪與自己的開發(fā)經(jīng)驗(yàn),給出如下一些觀點(diǎn)與建議,希望可以為你帶來一些幫助:
代碼除了完成指定功能,同時(shí)也是給人看的。優(yōu)美的代碼和優(yōu)美的風(fēng)景一樣,都能讓人感到賞心悅目,優(yōu)美的代碼是一種藝術(shù),相對(duì)于丑陋的代碼,大家都會(huì)傾向于查閱優(yōu)美的代碼。
在工作過程中,盡可能往編寫優(yōu)美代碼的方向走。
明了勝于晦澀
在代碼編寫中使用明了的詞語來命名方法名、函數(shù)名或變量名是非常好的習(xí)慣。命名很好的代碼,可以省略很多代碼注釋的工作,優(yōu)秀的代碼會(huì)說話。
編寫優(yōu)秀的代碼,代碼本身就是注釋。
最好的代碼是不需要注釋就可以讓大部分人都可以看懂,這需要編寫者有很強(qiáng)的編碼功底和語言抽象功能,很多時(shí)候并不要求所有開發(fā)這都有這種能力,但也需要在少量的代碼注釋情形下可以讓代碼閱讀者可以快速看明白你寫的代碼。
如果可能,盡量減少晦澀代碼的出現(xiàn),大部分情形下,晦澀代碼的出現(xiàn)都是因?yàn)殚_發(fā)者對(duì)需求了解不清楚或沒有用更簡(jiǎn)單的方式思考,對(duì)于代碼的負(fù)責(zé)人,若看到出現(xiàn)類似代碼,應(yīng)當(dāng)小心謹(jǐn)慎,需要了解對(duì)應(yīng)的需求是否確實(shí)會(huì)如代碼那么晦澀,還是開發(fā)人員想復(fù)雜了。
把簡(jiǎn)單的事情做復(fù)雜并不難,但要把復(fù)雜的變得簡(jiǎn)單,那需要付出巨大的艱辛。
在工程應(yīng)用中,把簡(jiǎn)單的需求做得復(fù)雜的案例數(shù)不勝數(shù);而能通過抽絲剝繭的方式把復(fù)雜應(yīng)用場(chǎng)景拆分的很簡(jiǎn)單的案例少之又少,當(dāng)今市場(chǎng)極為缺乏有這種能力的人才。
復(fù)雜的來源也是有很多當(dāng)時(shí)以為簡(jiǎn)單的事情堆積而成的,在多種簡(jiǎn)單的組合過程中,繼續(xù)保持整體的簡(jiǎn)單,是一件值得思考的事情,這要求在對(duì)整體了解的情況下對(duì)各個(gè)細(xì)節(jié)的把控,編程本來就是一門對(duì)細(xì)節(jié)要求極高的技術(shù),當(dāng)對(duì)細(xì)節(jié)的掌控了然于胸時(shí),編寫出簡(jiǎn)單的代碼就水到渠成了。
我們排斥復(fù)雜,但有時(shí)復(fù)雜難以避免。可以復(fù)雜,但不要凌亂。有跡可循的復(fù)雜代碼還是具有可讀性的,至少可以從代碼層面找到處理邏輯。
當(dāng)代碼以凌亂的方式出現(xiàn)時(shí),那是會(huì)讓人非常崩潰的。猶如你與人交談時(shí),若與你談話的人一直東一句,西一句,讓你根本不清楚對(duì)方在講什么,估計(jì)你與對(duì)方聊上幾分鐘就不想聊了,并期望不想再遇到類似的聊天對(duì)象。編程也一樣,對(duì)于那些凌亂的代碼,大家都是避之不恐。
在編寫代碼時(shí),每增加一個(gè)嵌套,則意味著代碼的復(fù)雜度增加了一些,代碼的執(zhí)行效率對(duì)應(yīng)的下降了一些。
當(dāng)出現(xiàn)三層以上的嵌套時(shí),那說明代碼編寫思路出現(xiàn)了偏差,對(duì)于這種代碼,應(yīng)該會(huì)非常浪費(fèi)系統(tǒng)的資源,甚至全部耗盡。實(shí)際應(yīng)用中應(yīng)當(dāng)避免,并尋求其它更簡(jiǎn)單的實(shí)現(xiàn)方式。
能用扁平的方式實(shí)現(xiàn)時(shí),就不要使用嵌套實(shí)現(xiàn)。
若是面向計(jì)算機(jī)編程,代碼間隔緊湊與否是沒有任何關(guān)系的。但若需要不斷被開發(fā)人員查看,適當(dāng)?shù)拈g隔那就非常有必要了,組織良好的代碼不僅僅是邏輯清晰,在代碼結(jié)構(gòu)上也是非常有講究的,很多時(shí)候都會(huì)遵循PEP8的規(guī)范,那樣寫出來的代碼是讓人賞心悅目的。
另一方面,這也能幫助你編寫出更加高效的代碼,因?yàn)橥ㄟ^合理的控制代碼結(jié)構(gòu),當(dāng)程序發(fā)生問題時(shí),組織良好的代碼結(jié)構(gòu)可以幫助你更快的找到問題。
很多時(shí)候,我們編寫的代碼除了讓計(jì)算機(jī)執(zhí)行指定的程序,另一個(gè)很重要的點(diǎn)就是給其他人查看。而代碼的可讀性決定了會(huì)有多少人愿意讀你的代碼。
現(xiàn)在很流行的一個(gè)詞叫開源代碼,對(duì)于開源代碼,可讀性在很大程度上決定了有多人愿意參與到這個(gè)開源中。
而對(duì)于項(xiàng)目應(yīng)用中,編寫一份可讀性非常高的代碼是非常必要的,盡管很多時(shí)候是以功能優(yōu)先。提高代碼的可讀性,不僅僅是一個(gè)自我的修煉過程,對(duì)于團(tuán)隊(duì)、甚至公司,都可以更好的減少開發(fā)、維護(hù)和學(xué)習(xí)成本的。
在代碼編寫過程中,不可避免會(huì)需要對(duì)某些特例提供支持,甚至有時(shí)為了可以支持特例,需要違背一些已有的好的原則。
當(dāng)有需要類似的操作時(shí),需要做更為全局的平衡,這個(gè)特例是否必須,是否有其它可處理方式,怎么最小化特例給其它原則帶來的破壞。
編寫代碼的首要原則是可用,在可用的基礎(chǔ)上才有可能執(zhí)行其它如性能優(yōu)化、效率提升等操作。
實(shí)用性與純粹性不同,純粹性更多體現(xiàn)在實(shí)驗(yàn)或驗(yàn)證性操作上,很少參與到真實(shí)環(huán)境中的應(yīng)用,而我們需要的是可以在真實(shí)環(huán)境中可用的代碼。
當(dāng)程序出現(xiàn)錯(cuò)誤時(shí),那已經(jīng)在提示我們程序中的某處代碼并沒有如我們想象的那么完美,它編寫有Bug或是有隱藏Bug,需要我們進(jìn)行正確的處理,若置之不理,很有可能埋下一顆定時(shí)炸彈,在某一刻讓你的程序直接崩潰,這種的代價(jià)往往都會(huì)不小。
在實(shí)際的應(yīng)用中,即時(shí)是很小的問題,也不要選擇忽視,建立起必要的異常管理,而不要等到問題發(fā)生時(shí)才進(jìn)行亡羊補(bǔ)牢的操作,殊不知可能會(huì)為時(shí)已晚。
計(jì)算機(jī)的世界是0或1的世界,是即是,非即非,沒有不確定性的存在,也沒有任何的猜測(cè)。
對(duì)于編寫的任何代碼,都應(yīng)該是清晰的,沒有歧義的,若出現(xiàn)有歧義或不清晰的情形,那表明開發(fā)者對(duì)需要通過代碼實(shí)現(xiàn)的問題理解不到位,或是有猜測(cè)的成分,這種都是需要杜絕的。
在編程的世界里,任何問題的解決辦法都有多種,但更多的時(shí)候我們需要的是最直接的方法,并最好只有一種最直接的方法。
如對(duì)編程語言的選擇,對(duì)于科學(xué)計(jì)算和人工智能相關(guān)的事情,最直接的選擇就是使用Python,這個(gè)對(duì)于目前來說是最直接的唯一選擇。
對(duì)于編程的過程,是一種知行合一的過程,光靠執(zhí)行很多時(shí)候并不能得到期望的結(jié)果,還需要伴隨思考的過程。越是大的項(xiàng)目,前期思考的時(shí)間占比就越多。在動(dòng)手之前先做一些計(jì)劃,對(duì)全盤先有一個(gè)大致了解,把可能遇到的問題,會(huì)存在的瓶頸,會(huì)占用時(shí)間比較多的步驟,需要協(xié)助的資源等先做一個(gè)前期的規(guī)劃,會(huì)非常有利于后期的執(zhí)行的。
若期望一開始就擼起袖子直接干,那不是一個(gè)很建議的方法,除非你對(duì)需要做的事情已經(jīng)非常熟悉,否則還是有必要認(rèn)認(rèn)真真想一想需要做什么。
如果方案難以描述明白,那么一定是個(gè)糟糕的方案
對(duì)于編程來說,編寫的應(yīng)該是一個(gè)確定的事情,并且已經(jīng)有可以描述明白的方案。
對(duì)于不清晰的方案,編程上更不可能清晰。
一個(gè)糟糕的方案只會(huì)誕生一個(gè)糟糕的項(xiàng)目,項(xiàng)目里面則包含各種晦澀的代碼。
若一個(gè)實(shí)現(xiàn)可以通過類似偽代碼的方式描述出來,這基本上是一個(gè)可行的方案,若可以通過偽代碼容易的描述,那很有可能是個(gè)好方案,真實(shí)的應(yīng)用上還有很多其它的外界因素,只有結(jié)合那些因素,才能完全的確定這是否是一個(gè)好的方案。
在編碼的過程中,命名的沖突是一個(gè)非常需要小心的問題,這種問題一般不容易發(fā)現(xiàn),出現(xiàn)問題時(shí)的查找并不容易,所以需要充分借助命名空間的理念,盡量避免如命名沖突的問題。
通過命名空間控制變量的作用域,可以起到很好的變量的相互隔離的效果。
結(jié)語:
編碼是一件快樂的事情,特別當(dāng)看到一些貌似不太可行的事情,通過編程的方式變?yōu)榭尚袝r(shí),會(huì)感到一種發(fā)自內(nèi)心深處的快樂。并且當(dāng)一群人通過群策之力,完成一件艱巨的任務(wù)時(shí),創(chuàng)造出一些amazing的事情時(shí),那是一種不可言喻的喜悅。
而編寫出如藝術(shù)般的代碼需要付出很多,也需要經(jīng)過時(shí)間的錘煉,但當(dāng)它出現(xiàn)在大家眼前時(shí),是需要一種心境的追求才可以企及,任何人都可以往這個(gè)方向追求,它沒有任何標(biāo)準(zhǔn),沒有任何約束,有的只是你的不斷創(chuàng)造,在計(jì)算機(jī)編程這塊沃土上,還有一個(gè)超大的空間等待更多的人去開拓。
新版Python蟒蛇書重磅上市!
助你系統(tǒng)掌握編寫高效、優(yōu)雅的Python代碼的方法
快速成長為一位高水平的Python開發(fā)工程師!

也可以加一下老胡的微信 圍觀朋友圈~~~
推薦閱讀
(點(diǎn)擊標(biāo)題可跳轉(zhuǎn)閱讀)
老鐵,三連支持一下,好嗎?↓↓↓
