六星源課堂:13個(gè)Python最佳編程技巧,新手越早知道越好!

作為一名軟件工程師,你在工作時(shí)應(yīng)盡量少寫代碼。碰到問題時(shí),你首先想到的不應(yīng)該是“我怎么解決這個(gè)問題”,而是“其他人是不是已經(jīng)解決了這個(gè)問題,我能使用他們的方案嗎?”如果你自己去解決一個(gè)常見的問題,很有可能別人已經(jīng)有了解決方案。先在網(wǎng)上檢索解決辦法,只有在確定沒人解決過該問題之后,才開始自己動手解決。

DRY是不要重復(fù)自己(Dont’t Repeat Yourself)的簡稱,指的是不要在程序中編寫重復(fù)的或是基本相同的代碼。正確的做法是將代碼封裝至函數(shù)中,后續(xù)可重復(fù)使用。
正交性:
正交性(Orthogonality)是《The Pragmatic Programmer》中提倡并普及的另一個(gè)重要編程原則。亨特和托馬斯認(rèn)為,“該術(shù)語已經(jīng)被用來表示某種獨(dú)立性或解耦化。如果兩個(gè)或多個(gè)事物之間的變化不會相互影響,那么它們之間就存在正交性。在設(shè)計(jì)優(yōu)良的系統(tǒng)中,數(shù)據(jù)庫代碼與用戶界面之間是正交的;調(diào)整用戶界面不會影響數(shù)據(jù)庫,替換數(shù)據(jù)庫也不會改變用戶界面?!睂?shí)踐中請牢記,“A不應(yīng)該影響B(tài)”。假設(shè)我們有兩個(gè)模塊module_a和module_b,module_a不應(yīng)對module_b中的內(nèi)容進(jìn)行修改,反之亦然。如果設(shè)計(jì)的系統(tǒng)中A會影響到B,而B又影響C,很快就會失去控制,系統(tǒng)將變得無法管理。
每個(gè)數(shù)據(jù)都只應(yīng)保存在一處:
假設(shè)手上有一個(gè)數(shù)據(jù),我們只需要將其存儲在一個(gè)地方。例如,我們正在開發(fā)用來處理手機(jī)號碼的軟件,其中有兩個(gè)函數(shù)要使用地區(qū)編號的列表,這里要確保程序中只有一個(gè)地區(qū)編號列表,而不是為每個(gè)函數(shù)重復(fù)創(chuàng)建。正確的做法是創(chuàng)建一個(gè)保存地區(qū)編號的全局變量。更好的解決方案則是將信息保存在文件或數(shù)據(jù)庫中。
函數(shù)只做一件事:
我們寫的每個(gè)函數(shù)應(yīng)該只做一件事。如果發(fā)現(xiàn)函數(shù)太長,請檢查其是否在完成多個(gè)任務(wù)。將函數(shù)限制為只完成一個(gè)任務(wù)有很多好處。首先,代碼可讀性增強(qiáng),因?yàn)楹瘮?shù)名稱可以直接說明其功能。如果代碼出錯(cuò),調(diào)試也將更加方便,因?yàn)槊總€(gè)函數(shù)只負(fù)責(zé)一個(gè)特定的任務(wù),我們可以快速隔離并調(diào)試問題函數(shù)。用許多知名程序員的話來說:“軟件的復(fù)雜性大多源自試圖兩件事當(dāng)一件事做?!?/p>
若耗費(fèi)時(shí)間過長,你的做法很可能就是錯(cuò)的:
如果你不是在處理非常復(fù)雜的問題,比如處理大數(shù)據(jù),但是程序卻要花很長時(shí)間才能加載,這時(shí)可以認(rèn)為你的做法很有可能錯(cuò)了。
第一次就要用最佳的方法完成:
在編程時(shí)你可能會這樣想:“我知道有一個(gè)更好的做法,但是我已經(jīng)開始編碼了,不想回頭重寫?!蹦俏医ㄗh你停止編碼,改用更好的方法來完成。
遵循慣例:
學(xué)習(xí)新編程語言的慣例,能夠提升閱讀用該語言編寫的代碼的速度。PEP8 是一系列編寫Python代碼的指南,強(qiáng)烈建議閱讀。
使用強(qiáng)大的IDE:
到目前為止,我們一直使用的是Python自帶的IDE——IDLE來編碼。但是IDLE只是眾多可選IDE中的一個(gè),而且我也不推薦長期使用它,因?yàn)槠涔δ苡邢蕖@纾绻褂酶鼜?qiáng)大的IDE打開Python項(xiàng)目,每個(gè)Python文件都會有不同的選項(xiàng)卡。在IDLE中則是每個(gè)文件新開一個(gè)窗口,操作煩瑣且文件之間來回切換困難。
筆者使用JetBrains公司開發(fā)的一款名為PyCharm的IDE。他們提供了免費(fèi)版和專業(yè)版兩個(gè)版本,這款I(lǐng)DE有如下特性能夠幫助我們節(jié)省時(shí)間。
1.如果想查看某個(gè)變量、函數(shù)或?qū)ο蟮亩x,PyCharm提供了一個(gè)快捷方式,可以跳轉(zhuǎn)到定義變量、函數(shù)或?qū)ο蟮牡胤剑词故橇硗庖粋€(gè)文件)。PyCharm還提供了跳回開始頁面的快捷方式。
2.PyCharm有保存本地歷史的特性,可以極大提升工作效率。PyCharm會在每次項(xiàng)目出現(xiàn)變動時(shí)保存一份,因此可以不推送到代碼庫,就能將PyCharm當(dāng)做一個(gè)本地版的版本管理系統(tǒng)。用戶不需要做任何操作,IDE將自動保存。在我了解該特性之前,我經(jīng)常會在解決問題后,想要換一種方案,但是不久后又希望回滾到原方案。如果我不把原方案推送到Github,很可能早就遺失了,不得不重新編寫。但是有了這個(gè)特性,我們就能回滾到10分鐘前,然后重新載入當(dāng)時(shí)的項(xiàng)目狀態(tài)。如果又改變主意,也可以隨意地在不同方案之前來回切換。
3.在日常工作過程中,很可能要經(jīng)常復(fù)制粘貼代碼。在PyCharm中,不需要復(fù)制粘貼,在當(dāng)前界面上直接移動代碼即可。
4.PyCharm支持Git和SVN等版本控制系統(tǒng)。無須使用命令行,即可直接在PyCharm中使用Git。在IDE和命令行之間切換次數(shù)越少,工作效率越高。
5.PyCharm提供了內(nèi)置的命令行和Python Shell。
6.PyCharm內(nèi)置了調(diào)試器(debugger)。調(diào)試器是支持中斷代碼執(zhí)行,逐行查看代碼效果的程序。通過調(diào)試器,我們可以查看不同代碼中變量的值。
記錄日志:
記錄日志(logging)指的是在軟件運(yùn)行時(shí)記錄數(shù)據(jù)的做法。我們可通過日志來協(xié)助程序調(diào)試,更好地了解程序運(yùn)行時(shí)的狀態(tài)。Python自帶了一個(gè)logging日志模塊,支持在控制臺或文件中記錄日志。
程序出錯(cuò)時(shí),我們不希望沒有感知——我們應(yīng)該記錄下相關(guān)信息,方便以后核查。記錄日志也有助于收集和分析信息。例如,可以搭建一個(gè)Web服務(wù)器來記錄數(shù)據(jù),包括每次收到請求的日期和時(shí)間。我們可以將所有的日志記錄在數(shù)據(jù)庫中,編寫程序分析其中的數(shù)據(jù),并生成圖表展示訪問網(wǎng)站的人次。
博客作者亨瑞克·沃納(Henrik Warne)在博客中寫過這樣一段話:“偉大程序員與平庸程序員的區(qū)別之一,就是偉大的程序員會做日志記錄,使得出錯(cuò)時(shí)的調(diào)試變得更簡單?!?/p>
測試:
程序測試指的是檢查程序是否“達(dá)到了設(shè)計(jì)和開發(fā)要求,對各類輸入返回正確的結(jié)果,功能執(zhí)行耗時(shí)在可接受范圍,可用性足夠高,可在目標(biāo)環(huán)境下安裝和運(yùn)行,并且實(shí)現(xiàn)了相關(guān)利益方所期待的效果?!睘榱诉M(jìn)行程序測試,程序員要額外編寫程序。
在生產(chǎn)環(huán)境中,測試是必須完成的。對于計(jì)劃部署在生產(chǎn)環(huán)境的程序,我們應(yīng)當(dāng)認(rèn)為在沒有編寫測試之前都是不完整的。但是,如果是一個(gè)不會再使用的臨時(shí)程序,測試可能有些浪費(fèi)時(shí)間。如果編寫的是其他人也將使用的程序,則應(yīng)該編寫測試。很多知名程序員都曾說過:“未經(jīng)測試的代碼就是漏洞百出的代碼?!?/p>
代碼審查:
在代碼審查(code review)時(shí),同事會閱讀你的代碼并提供反饋。建議盡可能多地進(jìn)行代碼審查,尤其對于自學(xué)成才的程序員來說。即使你遵守了本章中所列的所有最佳實(shí)踐,也有可能存在錯(cuò)誤的做法。你需要有經(jīng)驗(yàn)的程序員對你的代碼進(jìn)行檢查,指出所犯的錯(cuò)誤,這樣才有可能解決。
Code Review是一個(gè)專注于代碼審查的程序員社區(qū)。任何人都可以登入該網(wǎng)站,提交代碼。社區(qū)的其他成員會審查代碼,并反饋?zhàn)龅煤玫牡胤揭约翱梢愿倪M(jìn)的地方。
安全:
對于自學(xué)的程序員來說,安全是一個(gè)很容易忽視的問題。在面試時(shí)也很少會被問到安全問題,在學(xué)習(xí)編程時(shí)我們也不會去考慮安全問題。但是,在實(shí)際工作中,我們需要對自己代碼的安全性負(fù)直接責(zé)任。本節(jié)將給出幾個(gè)提高代碼安全性的建議。
我們在本書中已經(jīng)學(xué)習(xí)了使用sudo命令以根用戶的身份執(zhí)行命令。非必要情況下,務(wù)必不要在命令行使用sudo執(zhí)行命令,因?yàn)槿绻泻诳颓秩氤绦虻脑?,將會獲得根訪問權(quán)限。如果你是服務(wù)器管理員,還應(yīng)該禁止根用戶登錄。每個(gè)黑客都會盯著根賬號,在攻擊系統(tǒng)時(shí)是首要選擇的目標(biāo)。
另外,總是假設(shè)用戶的輸入是惡意的。部分惡意攻擊的發(fā)生,就是利用了可接受用戶輸入的程序漏洞,因此我們要假設(shè)所有的用戶輸入都是惡意的,并以此為依據(jù)進(jìn)行編碼。
另一個(gè)提高代碼安全性的策略,是最小化你的攻擊面積(attack surface),即黑客可從程序中提取數(shù)據(jù)或攻擊系統(tǒng)的相關(guān)區(qū)域。通過最小化攻擊面積,可以減少程序出現(xiàn)漏洞的可能性。最小化攻擊面積的幾種常見做法包括:避免保存敏感信息,賦予用戶最低的訪問權(quán)限,盡可能少用第三方庫(代碼量越小、漏洞越少),剔除不再使用的功能代碼(代碼量越小、漏洞越少)等。
避免以根用戶身份登錄系統(tǒng),不要信任用戶輸入,以及最小化攻擊面積,是確保程序安全性的幾個(gè)重要手段。但這還只是提升安全性的一小部分。我們應(yīng)該試著從黑客的角度進(jìn)行思考。他們會如何利用你的代碼?這樣可以幫助我們找到之前可能忽略的漏洞。有關(guān)安全的話題非常大,不是本書所能涵蓋的,因此建議大家時(shí)刻思考并學(xué)習(xí)如何提升安全性。布魯斯·舒奈爾(Bruce Schneier)對此的總結(jié)十分精辟:“安全是一種思維狀態(tài)。”
術(shù)語表:
生產(chǎn)代碼:某個(gè)產(chǎn)品中被用戶使用的代碼。
生產(chǎn):將軟件投入生產(chǎn),指的是對外正式發(fā)布。
DRY:一個(gè)編程原則,“不要重復(fù)自己”的英文簡稱。
正交性:該術(shù)語已經(jīng)被用來表示某種獨(dú)立性或解耦化。如果兩個(gè)或多個(gè)事物之間的變化不會相互影響,那么它們之間就存在正交性。在設(shè)計(jì)優(yōu)良的系統(tǒng)中,數(shù)據(jù)庫代碼與用戶界面之間是正交的;調(diào)整用戶界面不會影響數(shù)據(jù)庫,替換數(shù)據(jù)庫也不會改變用戶界面。
調(diào)試器:調(diào)試器是支持中斷代碼執(zhí)行,可逐行查看代碼效果的程序。通過調(diào)試器,我們可以查看不同代碼中變量的值。
日志記錄:指的是在軟件運(yùn)行時(shí)記錄數(shù)據(jù)的做法。
測試:檢查程序是否“達(dá)到了設(shè)計(jì)和開發(fā)要求,對各類輸入返回正確的結(jié)果,功能執(zhí)行耗時(shí)在可接受范圍,可用性足夠高,可在目標(biāo)環(huán)境下安裝和運(yùn)行,且實(shí)現(xiàn)了相關(guān)利益方所期待的效果?!?/p>
代碼審查:他人閱讀你的代碼并給予反饋的過程。
攻擊面積:黑客可從程序中提取數(shù)據(jù)或攻擊系統(tǒng)的相關(guān)區(qū)域。
以上就是本次分享的全部內(nèi)容,想學(xué)習(xí)更多編程技巧,歡迎持續(xù)關(guān)注六星源課堂!