如何提高代碼可讀性,再教你一招
Hello糖声,各位小伙伴,在前面的幾個章節(jié)中分瘦,我們重點講解了Python的編程規(guī)范蘸泻,其中對PEP8和Google編程規(guī)范進行了解讀,其中對代碼的縮進嘲玫、行數(shù)悦施、命名、注釋等都有明確的規(guī)范去团,似乎我們按照這樣的編程規(guī)范進行規(guī)范性寫代碼就可以了抡诞。
NO,我們還是要意識到一個關鍵性問題就是最早我問的那個問題土陪,你的代碼是寫給誰的昼汗?很顯然,肯定不僅僅是給機器去執(zhí)行的鬼雀,我們的代碼很多的時候是為了給人看顷窒,那就需要做到讓人能看懂和理解,所以才有了那些編程規(guī)范的要求源哩,但是另一個問題是你在不同的團隊或環(huán)境中寫的代碼是給不同的人閱讀和理解的鞋吉,那么此時遵守你們團隊的編程規(guī)范才是王道,在符合團隊或公司規(guī)范的情況下励烦,去使用前面我們所講解的編程規(guī)范才是正確的谓着。
那是不是我按照團隊或公司或官方指導的編程規(guī)范進行代碼的編寫就一定能夠讓人容易閱讀了呢?
其實在大多數(shù)情況下已經(jīng)可以了坛掠,因此編程規(guī)范非常重要赊锚,那么另外一個就是在這些基礎上,讓你的代碼盡可能的簡單屉栓、易讀改抡、邏輯清楚。那么除了遵守編程規(guī)范系瓢,還有什么辦法來提高代碼的可讀性呢阿纤?
我的想法就是分解代碼,很多情況下夷陋,我們的代碼都是錯中復雜欠拾,互相交織胰锌,這樣即便按照一定的編程規(guī)范,也依然很難使你的代碼變的具有可讀性藐窄,因此本章節(jié)我們通過幾個案例來看一下资昧,如何通過合理分解代碼來提高代碼的可讀性。
如何分解代碼
首先荆忍,我們來看兩個小代碼段
# 第一段代碼
if i_am_rich:
money = 100
send(money)
else:
money = 10
send(money)
# 第二段代碼
if i_am_rich:
money = 100
else:
money = 10
send(money)
在上面的代碼中格带,你可以看到兩段代碼的執(zhí)行是一樣的,但是第一段代碼中刹枉,send調(diào)用出現(xiàn)了兩次叽唱,因此我們把它修改變成第二段代碼,我們把send合并了微宝,而且達到了同樣的效果棺亭。其實就是去除了重復代碼,讓代碼更加易讀蟋软。
作為一個程序員镶摘,那么肯定要知道編程中一個核心思想就是不寫重復代碼,重復代碼基本都可以通過使用條件岳守、循環(huán)凄敢、函數(shù)和類來解決。而另一個核心思想就是湿痢,減少迭代層數(shù)贡未,盡可能讓代碼扁平化,讓代碼更加易讀蒙袍。我們經(jīng)常在很多業(yè)務邏輯比較復雜的地方俊卤,使用大量的判斷和循環(huán)。不過它可能會讓你的代碼失去閱讀性害幅。
再來看一個例子:
你能很好的閱讀或理解這段代碼嗎消恍?
def send(money):
if is_server_dead:
LOG('server dead')
return
else:
if is_server_timed_out:
LOG('server timed out')
return
else:
result = get_result_from_server()
if result == MONEY_IS_NOT_ENOUGH:
LOG('you do not have enough money')
return
else:
if result == TRANSACTION_SUCCEED:
LOG('OK')
return
else:
LOG('something wrong')
return
如果我們改造一下:
def send(money):
if is_server_dead:
LOG('server dead')
return
if is_server_timed_out:
LOG('server timed out')
return
result = get_result_from_server()
if result == MONET_IS_NOT_ENOUGH:
LOG('you do not have enough money')
return
if result == TRANSACTION_SUCCEED:
LOG('OK')
return
LOG('something wrong')
這樣會不會更加的清晰呢?
你看通過對代碼結構的調(diào)整以现,代碼一下就變得更加清晰狠怨,更具有易讀性。所以邑遏,我們除了遵守編程規(guī)范以外就是要有更好的程序邏輯的表達能力佣赖。具備這樣的能力才能寫出具備可讀性的代碼。
如何分解函數(shù)
接下來我們再看一個關于函數(shù)的代碼:
可以自己嘗試寫一下哦
下面是一個簡單的二分查找函數(shù)记盒,傳遞一個數(shù)組/列表 arr憎蛤,和一個查找目標target。要求找到數(shù)組中最小的一個數(shù)x,可以滿足x*x > target俩檬。如果不存在則返回-1
def solve(arr, target):
l, r = 0, len(arr) - 1
ret = -1
while l <= r:
m = (l + r) // 2
if arr[m] * arr[m] > target:
ret = m
r = m - 1
else:
l = m + 1
if ret == -1:
return -1
else:
return arr[ret]
print(solve([1, 2, 3, 4, 5, 6], 8))
print(solve([1, 2, 3, 4, 5, 6], 9))
print(solve([1, 2, 3, 4, 5, 6], 0))
print(solve([1, 2, 3, 4, 5, 6], 40))
你看上面的代碼萎胰,雖然已經(jīng)實現(xiàn)了目標∨锪桑可是在一個代碼中寫了判斷技竟、循環(huán)和運算,大多數(shù)人應該都會這樣做屈藐,這樣本身也沒錯榔组。可是联逻,我們應該讓一個函數(shù)的顆粒度盡可能的細一些搓扯,不應該讓一個函數(shù)處理太多的事情。所以遣妥,如果我們把這個復雜的函數(shù)進行分解,分成幾個功能單一又簡單的函數(shù)分別進行處理攀细,那么應該怎么做呢箫踩?
函數(shù)分解:
我們把不同的處理代碼進行了分離
- Comp作為運算的核心,只做數(shù)據(jù)的計算
- binary_search專門負責二分搜索
- solve函數(shù)負責拿到結果來判斷
def comp(x, target):
return x * x > target
def binary_search(arr, target):
l, r = 0, len(arr) - 1
ret = -1
while l <= r:
m = (l + r) // 2
if comp(arr[m], target):
ret = m
r = m - 1
else:
l = m + 1
return ret
def solve(arr, target):
id = binary_search(arr, target)
if id != -1:
return arr[id]
return -1
print(solve([1, 2, 3, 4, 5, 6], 8))
print(solve([1, 2, 3, 4, 5, 6], 9))
print(solve([1, 2, 3, 4, 5, 6], 0))
print(solve([1, 2, 3, 4, 5, 6], 40))
你看谭贪,這樣把一個復雜的函數(shù)分解成幾個功能單一的函數(shù)境钟,是不是就清晰了很多。
如何拆分類
最后俭识,我們再來看一下如何拆分類慨削。老規(guī)矩,先看代碼:
class Person:
def __init__(self, name, sex, age, job_title, job_description, company_name):
self.name = name
self.sex = sex
self.age = age
self.job_title = job_title
self.job_description = description
self.company_name = company_name
你應該能看得出來套媚,job 在其中出現(xiàn)了很多次缚态,而且它們表達的是一個意義實體,這種情況下堤瘤,我們可以考慮將這部分分解出來玫芦,作為單獨的類。
class Person:
def __init__(self, name, sex, age, job_title, job_description, company_name):
self.name = name
self.sex = sex
self.age = age
self.job = Job(job_title, job_description, company_name)
class Job:
def __init__(self, job_title, job_description, company_name):
self.job_title = job_title
self.job_description = description
self.company_name = company_name
你看本辐,改造后的代碼桥帆,瞬間就清晰了很多。
總結
怎么樣慎皱?通過上面的幾個案例是不是感覺到了代碼分解的重要性了呢老虫?抓緊看看你寫的代碼吧,當然如果以前的可能沒有很好的分解茫多,我覺得不要因為這個原因去動祈匙,原因你知道的?
所以天揖,希望大家通過本章的學習菊卷,能夠在未來的coding中注意代碼的可讀性進行合理的代碼分解缔恳。
如果喜歡本文或對你有幫助的話,歡迎大家關注我的公眾號:后廠程序員洁闰,并分享歉甚、點贊、在看 三連哦扑眉。