寫出漂亮 Python 代碼的 20條準則

2021-02-22 深度學習算法與計算機視覺

公眾號關注 「DL-CVer」

設為 「星標」,DLCV消息即可送達!

來自 | 架構頭條

按照《代碼整潔之道》的說法,「花在閱讀和編碼上的時間比遠遠超過 10:1。」

通常,當我們在學校學習時,編程美學不是一個關鍵問題。用 Python 寫代碼時,個人也會遵循自己的風格。然而,當我們必須花大把時間來理解一個人的隱式代碼時,這項工作肯定不受歡迎,這種情況同樣可能發生在別人閱讀我們的代碼時。所以,讓我們聚焦 Python 之禪和一些改進技巧,從而解決問題。

對於此前沒聽說過的人,請在 Python 解釋器中鍵入並執行import this,會出現由 Tim Peters 撰寫的 19 條指導原則:

優美勝於醜陋;

明了勝於晦澀;

簡單勝於複雜;

複雜勝於晦澀;

扁平勝於嵌套;

間隔勝於緊湊;

可讀性很重要;

特例不足以特殊到違背這些原則;

實用性勝過純粹;

永遠不要默默地忽視錯誤;

除非明確需要這樣做;

面對模稜兩可,拒絕猜測;

解決問題最直接的方法應該有一種,最好只有一種;

當然這是沒法一蹴而就的,除非你是荷蘭人;

做也許好過不做;

但不想就做還不如不做;

如果方案難以描述明白,那麼一定是個糟糕的方案;

如果實現容易描述,那可能是個好方案;

命名空間是一種絕妙的理念,多加利用!

在這篇文章中,我將分享自己對這些格言的理解以及我學到的一些有用的 Python 技巧。

Python 具有語法簡單、代碼可讀性強和命令類似英語等特點,這讓編寫 Python 代碼比使用其他程式語言更容易、更高效。例如,使用or and和|| &&構建語義相同的表達式:

# &&, ||if a == 0 && b == 1 || c == True:
# and, orif a == 0 and b == 1 or c == True:
# 這兩個邏輯表達式在 Python 中是相同的# 從語義的角度來看,可以使用選擇操作符來構造完全相同的表達式。

此外,代碼的布局和組成非常重要,有大量資源涉及這個主題。下面是最受歡迎也是我最喜歡的一個:PEP 8——Python 代碼風格指南。

https://www.python.org/dev/peps/pep-0008/

瀏覽完 PEP8 後,看看下面這些文章,其中展示了一些亮點和應用:

如何參照 PEP 8 編寫漂亮的 Python 代碼

https://realpython.com/python-pep8/

優雅的 Python 與 PEP8

https://medium.com/@mariasurmenok/stylish-python-with-pep8-c3ca93531418

PEP-8 的陷阱

https://medium.com/@ian.reinert/the-pitfalls-of-pep-8-b6108b006ed9

永遠不要弄亂你的代碼。要優雅而美麗。

在 Python 中,良好的命名約定不僅可以提升你的課堂成績,而且還能讓你的代碼更明了。幸運的是,你能在 PEP8 中找到一些指導原則,我想在下面強調其中的一些要點。

https://www.python.org/dev/peps/pep-0008/

一般來說,避免使用以下名稱:

太寬泛,如my_list;

太冗長,如list_of_machine_learning_data_set;

太模糊,如「1」、「I」、「o」、「O」。

包 / 模塊名應該全部小寫:

首選使用一個單詞命名;

當需要使用多個單詞時,使用下劃線分割它們。

類名應遵循 UpperCaseCamelCase 規範

變量方法函數應該採用小寫(如果需要,用下劃線分割)

常量名必須全大寫(如果需要,用下劃線分割)

一切都必須清晰易懂。

簡單比複雜更難:你必須付出巨大艱辛,化繁為簡。但這一切到最後都是值得的,因為一旦你做到了,你便能創造奇蹟。——賈伯斯

很多時候,在處理迭代器時,我們還需要保存迭代計數。Python 通過提供一個名為enumerate()的內置函數簡化這一任務。以下是一種不成熟的方法,然後是推薦方法:

words = [ Hannibal ,  Hanny ,  Steeve ]# 不成熟的方法index = 0for word in words:    print(index, word)    index += 1
# 推薦方法for index, word in enumerate(words): print(index, word)

另一個示例是使用內置的zip()函數,該函數創建一個迭代器,對來自兩個或多個迭代器的元素進行配對。你可以使用它來快速有效地解決常見的編程問題,比如創建字典。

subjects = [ math ,  chemistry ,  biology ,  pyhsics ]grades = [ 100 ,  83 ,  90 ,  92 ]grades_dict = dict(zip(subjects, grades))print(grades_dict)

化繁為簡的能力就是消除不必要的東西,保留必要的東西。

複雜(complex )和晦澀(complicated )的區別在於,複雜是指組件的系統層級,晦澀是指難度高。

有時候,儘管我們試圖讓任務變得簡單和傻瓜化,結果可能仍然很糟。

在這種情況下,編程優化變得很有必要,我最喜歡的學習方法是完成 coding challenge websites 上的工作。你可以查看其他人的解決方案,甚至能受到更好算法的啟發。

https://www.freecodecamp.org/news/the-10-most-popular-coding-challenge-websites-of-2016-fb8a5672d22f/

對於入門,HackerRank 提供了適合新手程式設計師的各種級別任務,這非常棒。之後,可以去嘗試更專業的網站,比如 Coderbyte 和 Topcoder。

嵌套模塊在 Python 中並不常見——至少我之前沒有見過像module.class.subclass.function這樣的東西——可讀性不好。雖然在另一個子模塊中構建子模塊可能會減少代碼行數,但我們不希望用戶被不直觀的語法所困擾。

不要在一行中插入太多代碼,這會給讀者帶來壓力。建議最大行長度 79 個字符。這樣,當使用代碼評審工具時,編輯器窗口寬度限制才能很好工作。


使用 Python 從 Unsplash 下載圖片

代碼的閱讀次數比編寫次數多。考慮下縮進,它讓代碼更容易閱讀,比較下面的代碼:

money = 10000000print("I earn", money, "dollars by writing on medium.")
money = 10_000_000print(f"I earn {money} dollars by writing on medium.")

在本例中,代碼結果相同,但是後一段代碼通過使用下劃線佔位符和 f-string 提供了更好的可讀性。在 Python 3.6 發布後,f-string 開始讓格式化變得更簡單,並且在處理包含更多變量的更長的句子時更強大。

一個作家的風格不應該在他的思想和讀者的思想間設置障礙。

關鍵是為一般情況提供一貫支持,嘗試將一個繁瑣的項目重新組織成一個簡單形式。例如,根據其功能,結構化類的代碼或將其分類到不同的文件中,即使 Python 並不強迫你這樣做。由於 Python 是一種多範式程式語言,解決問題的一個強大方法是創建對象,這就是所謂的面向對象編程。

面向對象編程是一種組織程序結構的編程範式,讓屬性和行為可以被看作是單獨對象。它的優點是直觀和易於操作,許多教程都很好地解釋了這些概念。

這句格言與前一句相矛盾,它提醒我們保持它們之間的平衡

放過錯誤最終會留下隱式 Bug,並且這些 Bug 更難被發現。Python 提供了健壯的錯誤處理,與其他語言相比,程式設計師使用該工具並不難。

try:    x = int(input("Please enter an Integer: "))except ValueError:    print("Oops! This is not an Integer.")except Exception as err:    print(err)else:    print( You did it! Great job! )finally:    print( ヽ(✿゚▽゚)ノ )
# 1. 這段代碼可能中斷。# 2. 如果出現值錯誤就會觸發。# 3. 處理值錯誤之外的錯誤。# 4. 如果沒有觸發錯誤就執行。# 5. 不管是否觸發錯誤都執行。

根據 Python 文檔:「即使一個語句或表達式在語法上是正確的,在試圖執行它時也可能會導致錯誤。」特別是對於大型項目,我們不希望在耗時的計算後,代碼崩潰。這就是異常管理的魅力所在。

在某些情況下,小錯誤不會困擾你。不過,也許你想捕獲特定錯誤。要獲得關於特定錯誤消息的更多細節,我建議閱讀官方的內置異常文檔並找到你需要的內容。

https://docs.python.org/3/library/exceptions.html

重要的是要不斷學習,享受挑戰,容忍歧義。我們都不知道最終會怎樣。——瑪蒂娜·霍納

這句話優雅而抒情,但在編程中不是一個好的隱喻。歧義可能是指不清楚的語法、複雜的程序結構或觸發錯誤消息的錯誤。例如,第一次使用numpy模塊時的一個簡單錯誤:

import numpy as np
a = np.arange(5)print(a < 3)if a < 3: print( smaller than 3 )

ValueError: 具有多個元素的數組的真值不明確,請使用 a.any() 或 a.all()

如果執行上面代碼,你將在輸出中發現一個由 5 個布爾值組成的數組,表明值在 3 以下。因此,if語句不可能確定狀態。消息中顯示的內置函數.all() 和.any()用於代替 And/Or。

import numpy as np
a = np.array([True, True, True])b = np.array([False, True, True])c = np.array([False, False, False])
print(a.all())print(a.any())
print(b.all())print(b.any())
print(c.all())print(c.any())

輸出表明,.all()僅在所有項都為True時才返回True,而.any()在有一項為True時就返回True。

14 解決問題最直接的方法應該有一種,最好只有一種

想想為什麼 Python 被描述為一種易於學習的程式語言。Python 具有非凡的內置函數 / 庫和高度的可擴展性,它鼓勵程式設計師優雅地編寫代碼。儘管有更多的解決方案可以提供靈活性,但對於同一個問題,它們可能會花費更多時間。

輸入 import antigravity 並執行

Python 之父 Guido van Rossum 是一位荷蘭程式設計師,他讓這句格言變得無可爭議。你不會聲稱自己比他更了解 Python……至少我不會。

照片來自 GitHub

你可以拖延,但時間不會,失去的時間一去不復返。——班傑明·富蘭克林

對於那些像我一樣患有拖延症,正在尋求改變的人,看看這個,和恐慌怪獸合作。

https://embed.ted.com/talks/tim_urban_inside_the_mind_of_a_master_procrastinator

另一方面,這個格言的另一個方面是阻止你過度計劃,這並不比看 Netflix 更有效率。

拖延和過度計劃的共同特徵就是「什麼都做不了。」

「做也許好過不做」並不意味著計劃沒用。把你的想法寫下來,設定一個要徵服的目標,比不想就做要好。

例如,我通常在每個星期天花一個小時來制定我的周計劃,並在睡覺前更新我明天的計劃,看看有什麼需要推遲的事情。

回想一下「複雜勝於晦澀」的理念。通常,晦澀的代碼意味著弱設計,特別是在像 Python 這樣的高級程式語言中。

然而,在某些情況下,其領域知識的複雜性可能會讓實現難以解釋,而如何優化讓其明晰易懂至關重要。這裡有一個規劃項目指南,可以給你提供幫助。

https://docs.python-guide.org/writing/structure/

使設計(甚至人們的生活)更容易,即使背景知識可能很深刻,這是編程的專業知識,我認為也是編程中最困難的部分。

利用 Python 的簡單性和可讀性來實現一些瘋狂的想法。

最後但同樣重要的是,命名空間是一組符號,用於組織各種對象,以便這些對象可以通過惟一的名稱引用。在 Python 中,命名空間是由以下元素組成的系統:

內置命名空間:可以在不創建自定義函數或導入模塊(如print()函數)的情況下調用。

全局命名空間:當用戶創建一個類或函數時,將創建一個全局命名空間。

局部命名空間:局部作用域中的命名空間。

命名空間關係圖

命名空間系統可以防止 Python 模塊名稱之間產生衝突。

https://medium.com/better-programming/how-to-make-python-programming-more-elegant-and-decent-4b5962695aa9

相關焦點

  • 這25條極簡Python代碼,你還不知道
    ,就被它的簡單性、出色的可讀性和特別流行的一行代碼所吸引。如果你嘗試用其他語言來做,你可能需要寫10行代碼,但是使用Python,我們可以只用一行代碼就實現FizzBuzz。['FizzBuzz' if i%3==0 and i%5==0    else 'Fizz' if i%3==0     else 'Buzz' if i%5==0     else i  for i in range(1,20)]在上面的代碼中,我們使用列表理解來運行一個從1到20的循環,然後在循環的每次迭代中,我們檢查數字是否能被3或5整除
  • 你必須掌握的20個python代碼,短小精悍,用處無窮
    當今python程式語言的潮流已經成為不可阻擋的趨勢,python以其較高的可讀性和簡潔性備受程式設計師的喜愛
  • Python編寫代碼規範-幫你寫出優雅的代碼
    在工作或實習中,掌握規範的代碼編寫能力是對代碼編寫人員的基本要求。
  • 代碼這樣寫更優雅(Python版)
    >今晚八點,不見不散作者:劉志軍,6年+Python使用經驗, 高級開發工程師,目前在網際網路醫療行業從事Web系統構架工作個人公眾號:Python之禪(微信ID:vttalk)題圖:unsplash.comPython 這門語言最大的優點之一就是語法簡潔,好的代碼就像偽代碼一樣,乾淨、整潔、一目了然。
  • Python代碼可以加密碼?Python字節碼告訴你!
    眾所周知,執行Python程序可以直接使用python.exe命令,如下所示:看到python直接執行了abc.py,可能很多同學認為python是解釋執行abc.py的,其實不然。如果要真是解釋執行,那效率慢的就沒法用了。實際上,Python與Java一樣,也是玩字節碼出身。Java的字節碼叫Java ByteCode,Python的字節碼叫Python ByteCode。
  • 謹記四條規則,便可寫出完美的Python命令行程序
    因此,我建議你遵循以下四條規則:  儘可能提供默認參數值所有錯誤情況必須處理(例如,參數缺失,類型錯誤,找不到文件)所有參數和選項必須有文檔不是立即完成的任務應當顯示進度條  舉個簡單的例子  我們把這些規則應用到一個具體的例子上。這個腳本可以使用凱撒加密法加密和解密消息。
  • Python代碼如何升級為Pythonic 代碼
    符合這樣要求的代碼也被python社區稱為pythonic的代碼。正文共:7841 字預計閱讀時間:20 分鐘Python是當今最流行的語言之一。相對較新的領域如數據科學、人工智慧、機器人和數據分析,以及傳統的專業如Web開發和科學研究等,都在擁抱Python。對於用Python這樣的動態語言編寫代碼的程式設計師來說,確保代碼的高質量和無錯誤變得越來越重要。
  • 【程序原始碼】《零基礎學編程-python》源碼包1
    1、培養邏輯思維能力2、培養發現問題和解決問題的能力3、促進其他學科的學習4、找份好工作  02  —【python簡介】程式語言有很多種:java / C / JS /GO 等。python的代碼簡潔、短小很容易掌握。這是他流行的一個主要原因之一。
  • Python 性能優化的20條招數
    python2.x 內置 generator 功能的有 xrange 函數、itertools 包等。如:a = range(2000) %timeit -n 100 [i for i in a if 10 < i < 20 or 1000 < i < 2000]%timeit -n 100 [i for i in a if 1000 < i < 2000 or 100
  • 論如何寫出詩一樣的代碼
    Rockstar,一門圖靈完備的程式語言,可以用來寫出詩一樣的代碼。。比如,it,he在代碼裡指代最近被命名的變量。而a=10則可以寫成 Put a into the 10 。變量可以帶空格,比如My heart is true。就是「My heart」=true 。。
  • 讓你的 Python 代碼優雅又地道
    —— Edsger Wybe Dijkstra在Python社區文化的澆灌下,演化出了一種獨特的代碼風格,去指導如何正確地使用Python,這就是常說的pythonic。一般說地道(idiomatic)的python代碼,就是指這份代碼很pythonic。Python的語法和標準庫設計,處處契合著pythonic的思想。
  • 20 道Python基礎練習題
    個等於255個gbk是中文編碼,是用的16個二進位代表一個漢字,有點浪費空間uft-8也是中文編碼,也是用的16個二進位代表一個漢字,但是能用8位表示就用位了4、請寫出「李傑」分別用utf-8的gbk編碼所佔的位數6   45、python單行注釋和多行注釋分別用什麼
  • 手把手教你寫垃圾代碼,從入門到精通
    如果說到什麼是好代碼,我們肯定都能說出一堆規則,例如使用一致的格式和縮進、使用清晰的變量名和方法名、在必要時提供文檔與注釋、不要過度精簡代碼等等。但是對於什麼是爛代碼,你有比較清晰的認識嗎?在 GitHub 上有一個新項目,它描述了「最佳垃圾代碼」的十九條關鍵準則。從變量命名到注釋編寫。這些準則將指導你寫出最亮眼的爛代碼。
  • python發布代碼教程
    (一)發布代碼首先做好發布前的準備工作。在D:\創建一個文件夾mymodule,其中包含mymodule.py和setup.py(包含發布的元數據)兩個文件。文件內容如下:mymodule.py是一個模塊文件,其內容就是tria函數。
  • 在Rust 代碼中編寫 Python 是種怎樣的體驗?
    ; run_python("print(\"... World!\")");}我們可以使用std::process::命令來運行python可執行文件並傳遞python代碼,從而實現run_python,但如果我們希望能夠定義和讀回Python變量,那麼最好從使用PyO3庫開始。
  • Python代碼技巧,你值得擁有!
    如何在命令行查看python文檔如何將python代碼打包成獨立的二進位文件需要編譯的python代碼如下:#!/usr/bin/env python# -*- coding: utf-8 -*-print 'hello, world!'將python代碼打包成獨立的二進位文件步驟:
  • 雙劍合璧,Python調用C代碼
    在本文中,我們將用C語言實現一個Python模塊,並在Python代碼中對其進行調用。首先我們創建一個.c文件,並且加入#include <Python.h>其中包含了必要的用C語言實現的Python對象setup.py接下來,我們利用Python中提供方法將C代碼作為擴展模塊加入到
  • Python性能優化的20條招數
    python2.x 內置 generator 功能的有 xrange 函數、itertools 包等。如:a = range(2000)  %timeit -n 100 [i for i in a if 10 < i < 20 or
  • 《代碼整潔之道》精讀與演繹】之四 優秀代碼的格式準則
    因為項目的緊迫性,需求的多樣性,我們無法時時刻刻都寫出整潔的代碼,保持自己輸出的都是高質量、優雅的代碼。  但若我們理解了代碼整潔之道的精髓,我們會知道怎樣讓自己的代碼更加優雅、整潔、易讀、易擴展,知道真正整潔的代碼應該是怎麼樣的,也許就會漸漸養成持續輸出整潔代碼的習慣。  而且或許你會發現,若你一直保持輸出整潔代碼的習慣,長期來看,會讓你的整體效率和代碼質量大大提升。
  • 一行代碼實現Python並行處理
    實例化 Pool 對象:pool = ThreadPool()這條簡單的語句替代了 example2.py 中 buildworkerpool 函數 7 行代碼的工作。我們來看看改寫後的 example2.pyimport urllib2from multiprocessing.dummy import Pool as ThreadPoolurls = [    'http://www.python.org',    'http://www.python.org/