聊聊Python

非同步社群發表於2017-09-06

Python很棒!

從20世紀80年代末出現的最早版本到當前版本,Python的發展一直遵循著相同的理念:提供一個同時具備可讀性和生產力的多正規化程式語言。


人們曾經將Python看作另一種指令碼語言,認為它不適合構建大型系統。但多年以來,在一些先驅公司的努力下,Python顯然可以用於構建幾乎任何型別的系統。



實際上,許多其他語言的開發者也醉心於Python,並將它作為首選語言。

1.1 Python的現狀與未來

Python的歷史最早可追溯到20世紀80年代末,但是1.0版的發行時間是在1994年,所以Python並不是一門非常年輕的語言。這裡本該介紹Python主要版本釋出的整個時間線,但其實真正重要的日期只有一個:2008年12月3日,也就是Python 3.0的釋出日期。

在寫作本書時,Python 3的首次釋出已經過去了7年。PEP 404也已經建立了4年,PEP 404是“取消釋出"(un-release)Python 2.8並正式關閉Python 2.x分支的官方文件。雖然過去了這麼長的時間,Python 社群中依然存在明顯的分歧。語言本身在迅速發展,但大量使用者卻並不想更新版本。

1.2 Python升級及其原因

原因很簡單。Python升級是因為有這樣的需求。語言之間的競爭隨時都在上演。每隔幾個月都會突然冒出一門新語言,聲稱解決了之前所有語言中存在的問題。對於大多數類似的專案,開發人員很快就會失去興趣,它們的名氣也只是一時炒作。

不管怎樣,這也表示存在著更嚴重的問題。人們之所以設計新的程式語言,是因為他們發現現有的語言無法以最佳方式來解決問題。認識不到這樣的需求是目光短淺的。此外,Python的使用範圍也越來越廣泛,人們發現它有許多可以改進的地方,也應該做出這樣的改進。

Python的很多改進往往是由特定應用領域的需求驅動的。其中最重要的領域是Web開發,這一領域需要Python改進對併發的處理。

有些變化只是由於Python專案的歷史原因導致的。這些年已經發現了Python的一些不合理之處,有些是標準庫模組結構混亂或冗餘,有些是程式設計缺陷。最初,釋出Python 3是要對這門語言進行較大的清理與更新,但結果顯示,這個計劃並沒有收到預期的效果。在很長一段時間內,很多開發人員對Python 3只是抱著好奇的態度而已,但希望這種情形正在好轉。

1.3 追蹤Python最新變化——PEP文件

Python社群有一種應對變化的固定方法。雖然各種各樣的Python語言修改意見主要在郵件列表(python-ideas@python.org)中進行討論,但只有釋出了名為PEP的新文件,新的變化才會生效。PEP的全稱是Python改進提案(Python Enhancement Proposal,PEP)。它是提交Python變化的書面文件,也是社群對這一變化進行討論的出發點。這些文件的整個目的、格式和工作流程的標準格式也都包含在一份Python改進提案中,也就是PEP 1文件(www.python.org/dev/peps/pe…

PEP文件對Python的作用十分重要,根據討論的主題,PEP主要有以下3種用途。

  • 通知:彙總Python核心開發者需要的資訊,並通知Python釋出日程。

  • 標準化:提供程式碼風格、文件或其他指導意見。

  • 設計:對提交的功能進行說明。

所有提交過的PEP都被彙總在一個文件中,就是PEP 0(www.python.org/dev/peps/)。…

如果你對Python語言的未來發展方向感興趣,但又沒時間跟蹤Python郵件列表中的討論,那麼PEP 0會是很好的資訊來源。它會告訴你,哪些文件已被接受但尚未實施,哪些文件仍在審議中。

PEP還有其他的用途。人們通常會問這樣的問題:

  • A功能為什麼要以這樣的方式執行?

  • Python為什麼沒有B功能?

大多數情況下,關於該功能的某個PEP文件已經給出了上述問題的詳細回答。很多提交的關於Python語言功能的PEP文件並沒有通過。這些文件可作為歷史資料來參考。

1.4 當前Python 3的普及程度

Python 3有許多強大的新功能,那麼它在社群中廣泛普及了嗎?遺憾的是,並沒有。有一個著名的網站叫“Python 3榮耀之牆(Python 3 Wall of Superpowers)”,裡面記錄了大多數常用軟體包與Python 3的相容性,不久前這個網站剛剛改名為“Python 3恥辱之牆(Python 3 Wall of Shame)”。目前這種狀況正在逐步改善,上述網站的軟體包列表中綠色的比例也在每月緩慢增加[1]。儘管如此,但這並不代表很快所有應用開發團隊都只使用Python 3。當所有常用軟體包都支援Python 3時,“我們所用的軟體包還沒有遷移到Python 3”這一常用藉口將不再適用。

造成目前這種狀況的主要原因是,將現有應用從Python 2遷移到Python 3上總是一項不小的挑戰。像2to3之類的工具可以進行程式碼自動轉換,但無法保證轉換後的程式碼100%正確。而且,如果不做人工修改的話,轉換後的程式碼效能可能不如轉換前。將現有的複雜程式碼庫遷移到Python 3上可能需要付出巨大的精力和成本,某些公司可能無法負擔這些成本。但這些成本可以分割成小份來逐步完成。一些優秀的軟體架構設計方法可以幫助其逐步實現這一目標,如面向服務的架構或者微服務。新的專案元件(服務或微服務)可以用新方法編寫,現有的專案元件可以逐步遷移。

長遠來看,將專案遷移到Python 3只有好處。根據PEP-404這份文件,Python 2.x分支將不會發布2.8版本。而且未來所有重要的專案(如Django、Flask和NumPy)可能都將放棄2.x的相容性,僅支援Python 3。

我個人對這個問題的觀點可能會引發爭議。我認為在建立新的軟體包時,最好鼓勵社群完全放棄支援Python 2。當然,這一做法極大地限制了這些軟體的適用範圍,但對於那些堅持使用Python 2.x的人來說,這可能是改變他們想法的唯一方法。

1.5 Python 3和Python 2的主要差異

前面已經說過,Python 3打破了對Python 2的向後相容。但它並不是完全重新設計的。而且,也並不是說2.x版本的Python模組在Python 3下都無法執行。程式碼可以完全跨版本相容,無需其他工具或技術在兩大版本上都可以執行,但一般只有簡單應用才能做到這一點。

1.5.1 為什麼要關注這些差異

本章前面說過我個人對Python 2相容性的看法,但是目前不可能完全忽視這一點。還有一些Python包(例如第6章將講到的fabric)十分實用,但可能短期內不會遷移到Python 3。

另外,有時我們還會受到所在公司的制約。現有的遺留程式碼可能非常複雜,遷移程式碼的費用難以承受。所以即使我們現在決定只用Python 3,短期內也不可能完全放棄Python 2。

如今想要自稱專業開發者,沒有對社群的回饋是說不過去的,所以幫助開源軟體開發者向現有軟體包中新增對Python 3的相容,可以很好地償還在使用這些軟體包時產生的“道德債(moral debt)”。當然,不瞭解Python 2和Python 3的差異是無法做到這一點的。順便提一下,對於Python 3新手來說,這也是一項很好的練習。

1.5.2 主要的語法差異和常見陷阱

要比較不同版本之間的差異,最好的參考資料就是Python文件。不過為了方便讀者,本節總結了其中最重要的內容。但不熟悉Python 3的讀者還是要去閱讀官方文件。

Python 3引入的重要差異一般可分為以下幾個方面。

  • 語法變化,刪除/修改了一些語法元素,並新增了一些新的語法元素。

  • 標準庫中的變化。

  • 資料型別與集合的變化。

1.語法變化

有些語法變化會導致當前程式碼無法執行,這些變化是最容易發現的,它們會導致程式碼根本無法執行。包含新語法元素的Python 3程式碼在Python 2中無法執行,反之亦然。由於刪除了某些元素,導致Python 2程式碼顯然無法與Python 3相容。執行有這些問題的程式碼時,直譯器很快就會丟擲SyntaxError異常。下面是一個無法執行的指令碼示例,只包含兩個語句,都會引發語法錯誤而無法執行:

 print("hello world") print "goodbye python2"

上述程式碼在Python 3中的實際執行結果如下:

$ python3 script.py File "script.py", line 2 print "goodbye python2" ^SyntaxError: Missing parentheses in call to 'print'

列出所有的語法差異會比較長,而且Python 3.x的新版本也會不時新增新的語法元素,在較早版本的Python中就會引發錯誤(即使在相同的3.x版本上也會報錯)。其中最重要的語法差異將會在第2章和第3章中講到,所以這裡無需全部列出。

與Python 2.7相比,刪除或改動的內容要相對少一些,下面給出最重要的變化內容。

  • print不再是一條語句而是一個函式,所以必須加上括號。

  • 捕獲異常的語法由except exc, var改為except exc as var

  • 棄用比較運算子<>,改用!=

  • from module import docs.python.org/3.0/referen…

  • 現在from .[module] import name是相對匯入的唯一正確的語法。所有不以點字元開頭的匯入都被當作絕對匯入。

  • sorted函式與列表的sort方法不再接受cmp引數,應該用key引數來代替。

  • 整數除法表示式(如1/2)返回的是浮點數。取整運算可以用//運算子,如1//2。這樣做的好處是浮點數也可以用這個運算子,所以5.0//2.0 == 2.0

2.標準庫中的變化

語法變化很容易發現,標準庫中的重大變化也是非常容易發現的。Python的每個後續版本都會向標準庫模組中新增、棄用、改進或完全刪除某些內容。在舊版Python(1.x和2.x)中也會定期有這樣的變化,所以出現在Python 3中並不讓人吃驚。大多數情況下,對於刪除或重組的模組(例如urlparse移到了urllib.parse),在執行直譯器時會對匯入語句丟擲異常。這樣的問題很容易發現。無論如何,為了確保能夠發現所有類似的問題,完整的程式碼測試覆蓋率是必不可少的。在某些情況下(例如使用延遲載入模組時),這個通常在全域性匯入時出現的問題並不會出現,直到在程式碼中將某些模組作為函式呼叫時才會出現。因此,在測試期間確保每行程式碼都要實際執行是很重要的。

技巧.tif 

延遲載入模組

延遲載入模組是指在全域性匯入時並不載入的模組。在Python中,import語句可以包含在函式內部,這樣匯入是在函式呼叫時才會發生,而不是在全域性匯入時發生。在某些情況下,模組的這種載入方式可能比較合理,但大多數情況下,這只是對設計不佳的模組結構的變通方法(例如避免迴圈匯入),通常應避免這種載入方式。當然,對於標準庫模組來說,沒有理由使用延遲載入。

3.資料型別與集合的變化

開發人員在努力保持相容性或只是將現有程式碼遷移到Python 3上時,需要特別注意Python中資料型別與集合的表示方式的變化。雖然不相容的語法變化或標準庫變化很容易發現,也很容易修復,但集合與資料型別的變化要麼難以察覺,要麼需要大量的重複工作。這樣的變化列表會很長,再次重申,官方文件是最好的參考資料。

不過,這一節必須講一下Python 3中字串處理方式的變化,因為這是Python 3中最具爭議也是討論最多的變化,儘管這是一件好事,使很多問題變得更加明確。

現在所有字串都是Unicode,位元組(bytes)需要加一個bB的字首。Python 3.0和3.1不支援使用u字首(例如u"foo"),使用的話會引發語法錯誤。不支援這個字首是引發所有爭議的主要原因。這導致難以編寫能夠相容Python不同分支的程式碼,2.x版需要用這個字首來建立Unicode。Python 3.3又恢復了這個字首,雖然沒有任何語法上的意義,只是為了簡化相容過程。

1.5.3 用於保持跨版本相容性的常用工具和技術

在Python不同版本之間保持相容性是一項挑戰。根據專案的大小不同,這項挑戰可能會增加許多額外的工作量,但絕對可行,也很值得去做。對於在許多環境中都會用到的Python包來說,必須要保持跨版本相容性。如果開源包沒有定義明確並經過測試的相容範圍(compatibility bound),是不太可能流行起來的。而且,對於只在公司網路封閉使用的第三方程式碼來說,也可以大大受益於在不同環境中的測試。

這裡應該注意,雖然這一部分內容主要關注Python不同版本之間的相容,但這些方法也適用於保持與外部依賴項之間的相容,外部依賴項包括不同的包版本、二進位制庫、系統或外部服務等。

整個過程主要分為3個部分,按重要性排序如下。

  • 定義並記錄目標相容範圍的及其管理方法。

  • 在每個環境中進行測試,並對每個相容的依賴版本進行測試。

  • 實現實際的相容程式碼。

告知相容範圍是整個過程中最重要的一部分,因為這可以讓程式碼使用者(開發人員)對程式碼的工作原理和未來的變化方式有一定的預期和假設。我們的程式碼可能用於多個不同專案的依賴,這些專案也在努力管理相容性,所以把程式碼相容性說清楚還是很重要的。

本書總是儘量給出幾個選擇,而不會強烈推薦某個特定選項,而這裡是少數幾個例外之一。目前來看,管理相容性未來變化的最佳方法,就是正確使用語義化版本(Semantic Versioning semver)的版本號。它是一個廣為接受的標準,用僅包含3個數字的版本識別符號來標記程式碼的變化範圍。它還給出瞭如何處理棄用的方法建議。下面是摘錄semver官網的摘要。

版本格式:主版本號.次版本號.修訂號,版本號遞增規則如下。

  • 主版本號(MAJOR):當你做了不相容的API修改。

  • 次版本號(MINOR):當你做了向後相容的功能性新增。

  • 修訂號(PATCH):當你做了向後相容的問題修正。

先行版本號及版本編譯資訊可以加到“主版本號.次版本號.修訂號”的後面,作為延伸。

測試時就會發現一個悲傷的事實,為了保證程式碼與每個依賴版本和每個環境(這裡環境指的是Python版本)都保持相容,必須在所有可能的組合中對程式碼進行測試。當然,如果專案的依賴很多,做到這一點基本是不可能的,因為隨著依賴版本數目的增加,組合的數目也會迅速增加。因此,通常需要做一些權衡,使得執行所有相容性測試無需花費數年的時間。第10章中介紹一般的測試,裡面也介紹了所謂的矩陣測試中工具的選擇。

提示.tif  

專案遵循semver的好處在於,通常只有主版本才需要測試,因為次版本和修訂版本中保證沒有向後不相容的變化。只有專案不違背這樣的約定,這種說法才能成立。不幸的是,每個人都會犯錯,許多專案中都出現了後向不相容的變化,甚至在修訂版本中也出現了這種變化。儘管如此,由於semver聲稱對次版本和修訂版本的變化保持嚴格的向後相容,那麼打破這個規則就可以視為bug,可以在修訂版本中進行修復。

如果明確定義了相容範圍並嚴格測試,那麼實現相容層就是最後一步,也是最不重要的一步。但是,每一位對這個話題感興趣的程式設計師都應該知道下列工具和技術。

最基本的就是Python的future模組。它將Python新版本中的一些功能反向遷移到舊版本中,採用的是匯入語句的形式:

 from future import <feature>

future語句提供的功能是和語法相關的元素,其他方法很難處理這些元素。這個語句只能影響它所在的模組。下面是Python 2.7互動式會話的例項,從Python 3.0中引入Unicode:

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit(Intel)] on win32Type "help", "copyright", "credits" or "license" for moreinformation.>>> type("foo") # 舊的字面值<type 'str'>>>> from future import unicode_literals>>> type("foo") # 現在變成了unicode<type 'unicode'>

下面列出了所有可用的future語句,關注2/3相容性的開發者都應該知道。

  • division:Python 3新增的除法運算子(PEP 238)。

  • absolute_import:將所有不以點字元開頭的import語句格式解釋為絕對匯入(PEP 328)。

  • print_function:將print語句變為函式呼叫,所以在print後面必須加括號(PEP 3112)。

  • unicode_literals:將每個字串解釋為Unicode(PEP 3112)。

future中的可選語句列表很短,只包含幾個語法功能。對於其他變化的內容,例如元類語法(第3章會講到這一高階特性),維持其相容性則困難得多。future語句也無法完全解決多個標準庫重組的問題。幸運的是,有些工具旨在提供一致可用的相容層。最有名的就是Six模組,提供了常用的2/3相容性的整個樣板。另一個很有前途但名氣稍遜的工具是future模組。

在某些情況下,開發人員可能不想在一些小型Python包裡新增其他依賴項。通常的做法是將所有相容性程式碼放在一個附加模組中,該模組通常命名為compat.py。下面是來自python-gmaps專案的compat模組例項:

 # -- coding: utf-8 -*- import sys if sys.version_info < (3, 0, 0): import urlparse # noqa def is_string(s): return isinstance(s, basestring) else: from urllib import parse as urlparse # noqa def is_string(s): return isinstance(s, str)

這樣的compat.py模組十分常見,即使是利用Six保持2/3相容性的專案也很常見,因為這種方法非常方便,用於儲存在不同版本的依賴包之間保持相容性的程式碼。

技巧.tif 

下載示例程式碼

你可以用自己的賬號在Packt的官方網站下載本書的示例程式碼檔案。如果你是在其他地方購買的本書,你可以訪問Packt的官方網站並註冊,檔案會直接通過郵件傳送給你。

下載程式碼檔案的步驟如下。

  • 用你的電子郵件地址和密碼登入或註冊我們的網站。

  • 將滑鼠指標懸停在頂部的SUPPORT選項卡上。

  • 單擊Code Downloads & Errata

  • Search框中輸入本書的名字。

  • 選擇你要下載程式碼檔案的書籍。

  • 從下拉選單中選擇本書的購買途徑。

  • 單擊Code Download

檔案下載完成後,請確保用下列軟體的最新版本對資料夾進行解壓或提取。

  • 在Windows上用WinRAR或7-Zip。

  • 在Mac上用Zipeg、iZip或UnRarX。

  • 在Linux上用7-Zip或PeaZip。

本書的程式碼包也託管在GitHub,網址為github.com/ PacktPublishing/Expert-Python-Programming_Second- Edition。在GitHub上還有大量圖書和視訊資源。去看一下吧!


1.6Python從入門到放棄


Python大全都在這兒了


本文摘自《Python高階程式設計(第2版)》


Python高階程式設計(第2版)    

Python高階程式設計(第2版)        




更多python好書  



www.epubit.com.cn/search?q=py…





影象說明文字
影象說明文字

相關文章