Python很棒!html
從20世紀80年代末出現的最先版本到當前版本,Python的發展一直遵循着相同的理念:提供一個同時具有可讀性和生產力的多範式編程語言。
python
人們曾經將Python看做另外一種腳本語言,認爲它不適合構建大型系統。但多年以來,在一些先驅公司的努力下,Python顯然能夠用於構建幾乎任何類型的系統。
git
實際上,許多其餘語言的開發者也醉心於Python,並將它做爲首選語言。
程序員
Python的歷史最先可追溯到20世紀80年代末,可是1.0版的發行時間是在1994年,因此Python並非一門很是年輕的語言。這裏本該介紹Python主要版本發佈的整個時間線,但其實真正重要的日期只有一個:2008年12月3日,也就是Python 3.0的發佈日期。 github
在寫做本書時,Python 3的首次發佈已通過去了7年。PEP 404也已經建立了4年,PEP 404是「取消發佈"(un-release)Python 2.8並正式關閉Python 2.x分支的官方文檔。雖然過去了這麼長的時間,Python 社區中依然存在明顯的分歧。語言自己在迅速發展,但大量用戶卻並不想更新版本。 編程
緣由很簡單。Python升級是由於有這樣的需求。語言之間的競爭隨時都在上演。每隔幾個月都會忽然冒出一門新語言,聲稱解決了以前全部語言中存在的問題。對於大多數相似的項目,開發人員很快就會失去興趣,它們的名氣也只是一時炒做。 網絡
無論怎樣,這也表示存在着更嚴重的問題。人們之因此設計新的編程語言,是由於他們發現現有的語言沒法以最佳方式來解決問題。認識不到這樣的需求是目光短淺的。此外,Python的使用範圍也愈來愈普遍,人們發現它有許多能夠改進的地方,也應該作出這樣的改進。 架構
Python的不少改進每每是由特定應用領域的需求驅動的。其中最重要的領域是Web開發,這一領域須要Python改進對併發的處理。 併發
有些變化只是因爲Python項目的歷史緣由致使的。這些年已經發現了Python的一些不合理之處,有些是標準庫模塊結構混亂或冗餘,有些是程序設計缺陷。最初,發佈Python 3是要對這門語言進行較大的清理與更新,但結果顯示,這個計劃並無收到預期的效果。在很長一段時間內,不少開發人員對Python 3只是抱着好奇的態度而已,但但願這種情形正在好轉。 編程語言
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文檔並無經過。這些文檔可做爲歷史資料來參考。
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的人來講,這多是改變他們想法的惟一方法。
前面已經說過,Python 3打破了對Python 2的向後兼容。但它並非徹底從新設計的。並且,也並非說2.x版本的Python模塊在Python 3下都沒法運行。代碼能夠徹底跨版本兼容,無需其餘工具或技術在兩大版本上均可以運行,但通常只有簡單應用才能作到這一點。
本章前面說過我我的對Python 2兼容性的見解,可是目前不可能徹底忽視這一點。還有一些Python包(例如第6章將講到的fabric
)十分實用,但可能短時間內不會遷移到Python 3。
另外,有時咱們還會受到所在公司的制約。現有的遺留代碼可能很是複雜,遷移代碼的費用難以承受。因此即便咱們如今決定只用Python 3,短時間內也不可能徹底放棄Python 2。
現在想要自稱專業開發者,沒有對社區的回饋是說不過去的,因此幫助開源軟件開發者向現有軟件包中添加對Python 3的兼容,能夠很好地償還在使用這些軟件包時產生的「道德債(moral debt)」。固然,不瞭解Python 2和Python 3的差別是沒法作到這一點的。順便提一下,對於Python 3新手來講,這也是一項很好的練習。
要比較不一樣版本之間的差別,最好的參考資料就是Python文檔。不過爲了方便讀者,本節總結了其中最重要的內容。但不熟悉Python 3的讀者仍是要去閱讀官方文檔。
Python 3引入的重要差別通常可分爲如下幾個方面。
語法變化,刪除/修改了一些語法元素,並添加了一些新的語法元素。
標準庫中的變化。
數據類型與集合的變化。
有些語法變化會致使當前代碼沒法運行,這些變化是最容易發現的,它們會致使代碼根本沒法運行。包含新語法元素的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
。
語法變化很容易發現,標準庫中的重大變化也是很是容易發現的。Python的每一個後續版本都會向標準庫模塊中添加、棄用、改進或徹底刪除某些內容。在舊版Python(1.x和2.x)中也會按期有這樣的變化,因此出如今Python 3中並不讓人吃驚。大多數狀況下,對於刪除或重組的模塊(例如urlparse
移到了urllib.parse
),在運行解釋器時會對導入語句拋出異常。這樣的問題很容易發現。不管如何,爲了確保可以發現全部相似的問題,完整的代碼測試覆蓋率是必不可少的。在某些狀況下(例如使用延遲加載模塊時),這個一般在全局導入時出現的問題並不會出現,直到在代碼中將某些模塊做爲函數調用時纔會出現。所以,在測試期間確保每行代碼都要實際運行是很重要的。
![]()
延遲加載模塊
延遲加載模塊是指在全局導入時並不加載的模塊。在Python中,
import
語句能夠包含在函數內部,這樣導入是在函數調用時纔會發生,而不是在全局導入時發生。在某些狀況下,模塊的這種加載方式可能比較合理,但大多數狀況下,這只是對設計不佳的模塊結構的變通方法(例如避免循環導入),一般應避免這種加載方式。固然,對於標準庫模塊來講,沒有理由使用延遲加載。
開發人員在努力保持兼容性或只是將現有代碼遷移到Python 3上時,須要特別注意Python中數據類型與集合的表示方式的變化。雖然不兼容的語法變化或標準庫變化很容易發現,也很容易修復,但集合與數據類型的變化要麼難以察覺,要麼須要大量的重複工做。這樣的變化列表會很長,再次重申,官方文檔是最好的參考資料。
不過,這一節必須講一下Python 3中字符串處理方式的變化,由於這是Python 3中最具爭議也是討論最多的變化,儘管這是一件好事,使不少問題變得更加明確。
如今全部字符串都是Unicode,字節(bytes
)須要加一個b
或B
的前綴。Python 3.0和3.1不支持使用u
前綴(例如u"foo"
),使用的話會引起語法錯誤。不支持這個前綴是引起全部爭議的主要緣由。這致使難以編寫可以兼容Python不一樣分支的代碼,2.x版須要用這個前綴來建立Unicode。Python 3.3又恢復了這個前綴,雖然沒有任何語法上的意義,只是爲了簡化兼容過程。
在Python不一樣版本之間保持兼容性是一項挑戰。根據項目的大小不一樣,這項挑戰可能會增長許多額外的工做量,但絕對可行,也很值得去作。對於在許多環境中都會用到的Python包來講,必需要保持跨版本兼容性。若是開源包沒有定義明確並通過測試的兼容範圍(compatibility bound),是不太可能流行起來的。並且,對於只在公司網絡封閉使用的第三方代碼來講,也能夠大大受益於在不一樣環境中的測試。
這裏應該注意,雖然這一部份內容主要關注Python不一樣版本之間的兼容,但這些方法也適用於保持與外部依賴項之間的兼容,外部依賴項包括不一樣的包版本、二進制庫、系統或外部服務等。
整個過程主要分爲3個部分,按重要性排序以下。
定義並記錄目標兼容範圍的及其管理方法。
在每一個環境中進行測試,並對每一個兼容的依賴版本進行測試。
實現實際的兼容代碼。
告知兼容範圍是整個過程當中最重要的一部分,由於這可讓代碼使用者(開發人員)對代碼的工做原理和將來的變化方式有必定的預期和假設。咱們的代碼可能用於多個不一樣項目的依賴,這些項目也在努力管理兼容性,因此把代碼兼容性說清楚仍是很重要的。
本書老是儘可能給出幾個選擇,而不會強烈推薦某個特定選項,而這裏是少數幾個例外之一。目前來看,管理兼容性將來變化的最佳方法,就是正確使用語義化版本(Semantic Versioning semver)的版本號。它是一個廣爲接受的標準,用僅包含3個數字的版本標識符來標記代碼的變化範圍。它還給出瞭如何處理棄用的方法建議。下面是摘錄semver官網的摘要。
版本格式:主版本號.次版本號.修訂號,版本號遞增規則以下。
主版本號(MAJOR
):當你作了不兼容的API修改。
次版本號(MINOR
):當你作了向後兼容的功能性新增。
修訂號(PATCH
):當你作了向後兼容的問題修正。
先行版本號及版本編譯信息能夠加到「主版本號.次版本號.修訂號」的後面,做爲延伸。
測試時就會發現一個悲傷的事實,爲了保證代碼與每一個依賴版本和每一個環境(這裏環境指的是Python版本)都保持兼容,必須在全部可能的組合中對代碼進行測試。固然,若是項目的依賴不少,作到這一點基本是不可能的,由於隨着依賴版本數目的增長,組合的數目也會迅速增長。所以,一般須要作一些權衡,使得運行全部兼容性測試無需花費數年的時間。第10章中介紹通常的測試,裏面也介紹了所謂的矩陣測試中工具的選擇。
![]()
項目遵循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兼容性的項目也很常見,由於這種方法很是方便,用於保存在不一樣版本的依賴包之間保持兼容性的代碼。
![]()
下載示例代碼
你能夠用本身的帳號在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好書
www.epubit.com.cn/search?q=py…
![]()
圖像說明文字