在 Python 3 出現(xiàn)之前币厕,Python 在我眼里一直都是一位穩(wěn)重扎實的大叔,資歷深厚康吵,語法簡單劈榨,功能強(qiáng)大,兼顧面向?qū)ο蠛秃瘮?shù)式編程晦嵌,庫包豐富程度也讓其他語言轉(zhuǎn)過來的程序員瞠目結(jié)舌并喟嘆:人生苦短同辣,要用 Python 啊……這種情況一直持續(xù)到 Python 3 的出現(xiàn)。
一種語言版本的升級是極為普通且常見的事情惭载,不升級才算的上不正常旱函,但是Python 3 算的上是一個例外,因為 Python 3 放棄了向下兼容描滔,也就是說棒妨,你在 Python 2 系列版本中寫的代碼,一直好好的運(yùn)行著含长,只要放到 3 的環(huán)境里券腔,就有 99% 的可能性不能正常運(yùn)行了。最簡單的拘泞,你在 Python 2 中打印語句print "Hello World"纷纫,放到 Python 3 里,系統(tǒng)會告訴你「SyntaxError: Missing parentheses in call to 'print'」陪腌。刺激不刺激辱魁?
Python 的開發(fā)者這么做是為什么呢,或者說Python 3為什么會出現(xiàn)呢诗鸭?在很長的一段時間之內(nèi)染簇,沒有人出來解釋這件事,Python 的創(chuàng)造者們認(rèn)為强岸,這不是很顯然易見的嘛锻弓。這就好比一個有著超高幽默感的人就算是聽到了一個冷笑話也能樂得前仰后合哈哈大笑,另一個人 —— 比如普通開發(fā)者 —— 卻把一顆冰涼的花生米放嘴里邊嚼邊問请唱,哥們弥咪,你特么到底在笑啥呢过蹂?
Python 3為什么會存在呢?Brett Cannon —— Python 的核心開發(fā)者 —— 在一次問答活動中終于給出了一個合理的解釋聚至。在此之前他一直神奇的認(rèn)為大家都清楚知道 Python 3 為什么會出現(xiàn)酷勺。他說:
回想起來我真是太傻了,竟然會認(rèn)為大部分人 —— 不管是剛接觸 Python 或者已經(jīng)學(xué)過Python有一段時間 —— 要么應(yīng)該知道扳躬,要么就會充滿好奇心去獲取一個解釋或答案脆诉。然而并沒有。所以我來解釋一下 Python 3 為什么會存在贷币。兼容性為什么要被破壞击胜,改變 unicode/str/bytes,使得老代碼移植到 Python 3 非常困難役纹。
最根本的原因是偶摔,中文本和二進(jìn)制數(shù)據(jù)在 Python 2 中是一個爛攤子。比如在 Python 3 中促脉, 'abcd' 這個表達(dá)式辰斋,語義非常明確,就是包含了四個字母的字符串瘸味,但是四個字母的字符串宫仗,在 Python 2 里,也可以代表 97旁仿、98藕夫、99、100 的數(shù)組枯冈。你可以使用 print ord('a') 獲取到這個字母的 ASCII毅贮。總之尘奏,對于 str 代表的含義嫩码,在 Python 2 中就有兩種,這改變了語言的唯一性罪既。而在 Python 3 中答案是唯一的。
「Python之禪」就有講過铡恕,「找到一種或著唯一的一種解決方案就是去解決問題」琢感。文字既能代表文本數(shù)據(jù)又能代表二進(jìn)制數(shù)據(jù)這樣就會很麻煩。一旦對象脫離我們的控制探熔,就會讓人變得恐慌驹针。有人說我們可以用 Unicode,但是實際中的人們并不會那樣去做诀艰,有時還會引起不必要的麻煩柬甥。比如中文顯示饮六,在 Python 2 中是這樣的:
>>> geektime = “極客時間”>>> geektime'\xe6\x9e\x81\xe5\xae\xa2\xe6\x97\xb6\xe9\x9\xb4'
Python 3 就簡明很多:
>>> geektime = “極客時間”>>> geektime'極客時間'
簡化語言,移除 str 的二義性就能夠減少代碼的出錯率苛蒲。避免出 bug 是一件很重要的事情卤橄,但卻常常被人遺忘。Python 之禪中的另一句話「清晰勝于晦澀」也是表達(dá)了這個意思臂外,歧義和隱性知識使得代碼不容易溝通窟扑,并容易形成 bug。
正如 Brett Cannon 所言漏健,人們有時會忘記 Python 有多久的歷史了
1989年的冬天嚎货,Guido 開始編寫 Python 語言的編譯器和解釋器,為了度過一個有意義的圣誕節(jié)蔫浆。1991年2月殖属,第一個 Python 版本誕生,編譯器是用 C 語言實現(xiàn)的瓦盛。這意味著自從Python的出現(xiàn)早于 1991年10月發(fā)布的第一版 Unicode 標(biāo)準(zhǔn)后洗显。后面再出現(xiàn)的語言,比如 Java谭溉,Ruby 等都選擇在支持 Unicode 的標(biāo)準(zhǔn)上實現(xiàn)自己的 str 類型墙懂,這就讓 Python 3 變得比較尷尬。2004年 Python 3 的方案開始醞釀扮念,這時開發(fā)者們才意識到损搬,支持 Unicode 和來自任何語言的的文本是非常重要的。
Python 是一門面向世界的語言柜与,而不僅僅是那些支持 ASCII 碼覆蓋的羅馬數(shù)字的語言巧勤。這就是 Python 3 在處理文本時要選擇使用 Unicode 的原因。
Python 3 的開發(fā)過程大致是這樣的:
在 2004 年我們開始設(shè)計 Python 3弄匕。我們清楚知道 Python 的受歡迎程度在不斷上升颅悉,我們也希望能夠延續(xù)這種勢頭。但同時這也意味著如果我們想要及時修正所有的設(shè)計缺陷來保證它的受歡迎度迁匠,趁現(xiàn)在最好而不是以后剩瓶。我們設(shè)想 Python 3 相較于 Python 2 會有持續(xù)更長的一段時間,而不是 Python 2.7 只是用來維護(hù)以前遺留的項目城丧,新項目中重不會用到延曙,那用 Python 3 寫出的代碼一定會比用 Python 2 的更多。所以我們才決定來承受由 Python 2 向 3 轉(zhuǎn)型之痛亡哄,換來更好的枝缔。并且在這種設(shè)想下開發(fā)了 Python 3。
以后這種打破向后兼容性的事情我們再也不會做了蚊惯。
然而事情顯然沒有開發(fā)者想象的那么簡單愿卸,由于向下的兼容性的缺乏灵临,并且 Python 2 中的代碼歷史悠久,庫包豐富趴荸,而且大部分程序都是生產(chǎn)環(huán)境的應(yīng)用儒溉,遷移成本太高,沒有那么多顯而易見的好處赊舶。另外睁搭,由于 Python 2 是如此好用以至于開發(fā)者們掌握了熟練的技巧從而避免 str 帶來的陷阱。發(fā)布完 Python 3 之后笼平,Python 的核心開發(fā)者們都認(rèn)為社區(qū)會最終摒棄上一個版本园骆,痛痛快快的向著新世界轉(zhuǎn)向。但事與愿違寓调,兩個版本并存的情況持續(xù)了近十年之久锌唾。導(dǎo)致Python 的開發(fā)者們又要花費(fèi)更多的時間設(shè)計了一個對 Python 2/3 的兼容子集來實現(xiàn)這種過渡。
關(guān)于 Python 2 和 3的主要區(qū)別夺英,可以參考這篇文章:
http://www.runoob.com/python/python-2x-3x.html
那么該學(xué) Python 2 還是 Python 3 呢晌涕?如果要是五年前我會推薦學(xué)習(xí) Python 2,兩年前我推薦都要學(xué)都要掌握痛悯,事實上在 Mac 環(huán)境里用 homebrew 安裝和使用兩個版本的環(huán)境是非常方便的余黎。時至今日,大量的庫已經(jīng)開始普遍支持 Python 3 了载萌,而且 Python 3 的特性已經(jīng)遠(yuǎn)遠(yuǎn)不是解決 str 問題了惧财,所以我現(xiàn)在會推薦你直接學(xué)習(xí) Python 3。
看看 Instagram 的案例扭仁,在相當(dāng)長的一段時間垮衷,Instagram 都跑在 Python 2.7 + Django 1.3 的組合之上。經(jīng)過一系列的討論之后乖坠,他們最終做出一個重大的決定:升級到 Python 3搀突。
Python 3 有什么優(yōu)勢呢?新特性熊泵,比如如何類型注解 Type Annotations仰迁;提供了更好的性能;并且社區(qū)的支持重心已經(jīng)完全遷移到 Python 3顽分,還有什么理由再去使用 Python 2 呢轩勘?