五大代碼異味:你須要提升警戒了!

做爲普遍應用的警告標誌,與字面意思不一樣,代碼異味並非指代碼中須要當即注意的漏洞。相反,它反映出代碼中更深層次的問題,更確切地說是代碼中的裂縫,若是不加以糾正,這些問題可能會在將來致使更嚴重的後果。程序員

代碼異味是弱點或設計缺陷的標誌,可能會在可讀性、可維護性和可拓展性上致使問題,一般是由不當作法和未使用正確的工具致使的。面試

Python是最流行的語言之一,這在很大程度上與其至關容易的學習曲線和高度僞英語句法有關,而這卻容易使人陷入單一的作事方法。本文中,咱們將瞭解一些典型的Python代碼異味案例以及如何避免它們。安全

可變默認參數

在Python中,使用默認參數是一個很常見的操做,你能夠設置一個預約值,並在調用時選擇更改。這在設置文字、數字或布爾值時頗有用,由於有助於避免出現較長的有冗餘值的參數列表。架構

可是將可變的值設置爲默認參數多是危險的,而且會致使bug。來看如下示例:app

def addElements(a=[]):
    a.append(5)
    return aaddElements()
# [5]
addElements()
# [5, 5]

相同的函數在每次調用時給出不一樣的結果。Python中可變默認值的問題是它們只在定義函數時計算一次。每次調用函數時,使用變異值,可能會致使意外的問題,由於跟蹤函數調用真的很麻煩。運維

所以,使用None做爲默認值,並在函數中分配可變變量是更安全的,由於你不會以可維護性問題結束,只有在肯定須要時才使用可變的默認參數。分佈式

選擇 range 而不是enumerate

Python的for循環不是最經常使用的代碼編寫方式,但有時也會須要到。如今,Python中的for 循環的運行與其餘語言不一樣,你可能會本能地以非慣用的方式編寫傳統風格的range(len()),以下所示:函數

names =["a", "b", "c"]for i in range(len(names)):
    print(i, names[i])

重複基於C-style索引的循環是至關常見的,但這是一種不當作法。其迫使你經過顯式索引變量訪問元素,因此它不只Python特性不明顯,並且還存在可讀性問題。工具

使用enumerator能提供一個元組的優點,該元組負責同時跟蹤索引值和元素。除了更簡便,優化程度還更高,它還提供了可選的第二個參數來設置數值。oop

for i, name in enumerate(names):
   print(i, name)

忽略內置函數和過分循環

循環不是不能用,但在其中應用轉換操做時,它可能會致使冗長的條件代碼。在這種狀況下,不要忽略已經可使用的內置函數,如map()filter()和reduce(),這是很是重要的。更重要的是,Python提供了列表解析,這顯然是最具Python特性的替換循環方法。

嵌套for循環是代碼異味的另外一個典型例子。Python程序員在進行模式匹配或一塊兒運行多個迭代時很容易中槍。下列代碼一旦再加幾行就會看起來不美觀:

for x in listA:
    for y in listB:
        r.append((x, y))

使用itertools不只能夠提升性能,還更簡潔明瞭。看看上面的代碼在itertools.product()中有多整潔:

for x, y in itertools.product(listA,listB):    
    r.append((x, y))

經過使用上面的product,也能夠很容易地將其傳遞到其餘高階函數中。同時在多個列表上同時迭代時,使用zip()函數也不錯(如需索引,還可使用enumerator)。

濫用列表解析

列表解析能靈活建立列表,功能強大,但很容易被誤用或濫用,來看一些案例。

在不須要時過分進行列表解析
一般,咱們開始沉迷於使用列表解析是爲了嘗試花哨的東西,而不是真須要它。好比在簡單的狀況下可使用列表構造函數:

names =["A","B","C"][x.lower() for x in names]#use this
list(map(str.lower, names))

在實際不存儲時使用列表解析

列表解析有助於輕鬆定義和建立列表,但它們始終存儲於內存中。若是不使用系統進程,將有可能損害大數量的數據。所以,使用生成器表達式是更好的選擇,由於它按需一次加載一個值。

嵌套分析也須要關注,由於這可能致使可讀性問題,知道何時使用它,何時回退到for循環上是很重要的。

喜歡布爾標誌參數和全局變量

布爾是最容易學習的數據類型。在Python中,提供命名參數使工做輕鬆得多。可是,它們很容易產生嵌套if else塊的複雜代碼並致使可讀性問題。多個布爾存在隱藏的依賴關係,會產生一些問題。於是最好使用枚舉,而不是多布爾邏輯。Enum數據類型是可擴展的,能夠確保更好的代碼結構。

全局變量在全部語言中都是麻煩的,Python也是如此。雖然有時咱們確實須要使用它們,但將其誤用做傳遞或訪問數據的快捷方式可能很危險,由於它可變。

跟蹤它的狀態會很棘手,由於你永遠不知道誰可能會改變它。若是開始處處使用全局變量,命名衝突則會致使命名空間受到很差的影響。

咱們都見過代碼異味,神祕的註釋、多餘的字符串文字和神奇的數字也算代碼異味。在編寫註釋時,重要的是要說明「爲何」部分,由於「什麼」部分應該從代碼自己獲得解釋。

你得學會快速定位到代碼異味並將其去除。

※更多文章和資料|點擊後方文字直達 ↓↓↓
100GPython自學資料包
阿里雲K8s實戰手冊
[阿里雲CDN排坑指南] CDN
ECS運維指南
DevOps實踐手冊
Hadoop大數據實戰手冊
Knative雲原生應用開發指南
OSS 運維實戰手冊
雲原生架構白皮書
Zabbix企業級分佈式監控系統源碼文檔
雲原生基礎入門手冊
10G大廠面試題戳領
相關文章
相關標籤/搜索