兩個問題
學了 Python 基礎(chǔ)就夠了嗎?
前言的引言給出了答案:
要不這樣吧,如果編程語言里有個地方你弄不明白,而正好又有個人用了這個功能,那就開槍把他打死。這比學習新特性要容易些,然后過不了多久,那些活下來的程序員就會開始用 0.9.6 版的 Python,而且他們只需要使用這個版本中易于理解的那一小部分就好了(眨眼) 。
—— Tim Peters
傳奇的核心開發(fā)者, “Python 之禪”作者
這本書的目的是什么?
第十一章的雜談里給出了答案:
這正是本書的主要目的:著重講解這門語言的基本慣用法,讓你的代碼簡潔、高效且可讀,把你打造成熟練的 Python 程序員。
另外本書的前言里也有提及書本的目標讀者和非目標讀者。
如果你才剛剛開始學 Python,本書的內(nèi)容可能會顯得有些“超綱”。比難懂更糟的是,如果在學習 Python 的過程中過早接觸本書的內(nèi)容,你可能會誤以為所有的 Python 代碼都應該利用特殊方法和元編程(metaprogramming)技巧。我們知道,不成熟的抽象和過早的優(yōu)化一樣,都會壞事。
對內(nèi)容的一些評價
從書目錄結(jié)構(gòu)來看,作者的眼界十分開闊,每章最后有小結(jié)、延伸閱讀、和相關(guān)的一些雜談。書的前一部分從 Python 特性出發(fā),參考了很多語言的相關(guān)做法和實現(xiàn),來解釋 Python 的設(shè)計。
書中時常引用一些參考資料,有些是郵件列表里的討論、維基百科、一些十分優(yōu)秀的程序員的撰寫的文章和演講視頻。這意味著你可以在某一個概念看到不同的觀點,看到優(yōu)秀的程序員是怎么思考一個問題的。
作者從1998年成為了 Python 程序員,是巴西一家培訓機構(gòu)的共同所有者,也為巴西的媒體、銀行和政府部門教授 Python 課程,由此可見本書的代碼會是十分透徹和淺顯易懂的,事實也的確如此。從代碼示例來看,作者為大部分代碼提供了 doctest 測試,并且在為某一個知識點提供代碼示例時,追求的是簡單、直接,同時示例的難度是循序漸進的。加上作者在大部分代碼行提供了說明,讓讀者能十分流暢地理解概念。(對比:《Go 程序設(shè)計語言》講復數(shù)語法時用 Mandelbrot 圖像作為示例,苦笑)
對翻譯的一些評價
整體翻譯還是不錯的,幾百頁的書的勘誤也才十多個,部分術(shù)語可能還要參考書里的術(shù)語翻譯表,個人認為容易弄混的有特性(properties)和屬性(attributes),還有函數(shù)(function)和方法(method)。后者的區(qū)別可以參考Difference between a method and a function,簡單的說法就是函數(shù)(function)定義在類外面,而方法(method)定義在類里面,是類的一部分。兩者也可以根據(jù)是否獨立于對象來判斷。
黃志斌:這本書第2次印刷時已經(jīng)把“期物”改為“future”了。
P21 前面那種方式顯然能夠節(jié)省內(nèi)存。 前者指的是 genexp,即生成器表達式。
讀后感
這本書的結(jié)構(gòu)十分優(yōu)秀,每一章節(jié)都有前言和小結(jié),因此讀后感我偏向于寫些零散的知識點和個人感受,會比較亂。大部分章節(jié)的讀后感最后會有個人閱讀時做的筆記,讀后感沒提及的內(nèi)容可以看看我的筆記。
第一章
第一章作者就介紹了 Python 中的特殊方法,特殊方法也是貫穿這本書的基礎(chǔ)。
讀這本書之前,自己通常會遇到__init__、__new__、__name__ == '__main__'等等的帶雙下劃線的特殊方法,但是通過零散的知識點很難形成體系,而這本書涵蓋了絕大部分的特殊方法,并且分章節(jié)詳細地討論其背后特殊方法的作用,而這一章就是了解特殊方法的第一步。
作者提到了合理的字符串表示形式:__repr__ 和 __str__。前者方便我們調(diào)試和記錄日志,后者則是給終端用戶看的。
作者開篇就提出了兩個問題,第一個問題是:
為什么說 Python 最好的品質(zhì)之一是一致性?
并且在第十二頁給出了答案:
不能讓特例特殊到開始破壞既定規(guī)則。
第二個問題是:
len(collection)和collection.len()有什么不同?和“Python 風格” (Pythonic)有什么關(guān)系?
核心開發(fā)者 Raymond Hettinger 的答案是:
實用勝于純粹
practicality beats purity
——《The Zen of Python》
作者給出解釋:
len 是特殊方法,是為了讓 Python 自帶的數(shù)據(jù)結(jié)構(gòu)可以走后門,abs 也是同理。(解釋:因為如果 x 是一個內(nèi)置類型的實例,
len(x)的背后會用 CPython 直接從 C 結(jié)構(gòu)體中讀取對象的長度,不調(diào)用任何方法,以至于len(x)會非常快。)
...
這種處理方式在保持內(nèi)置類型的效率和保證語言的一致性之間找到了一個平衡點,也印證了“Python 之禪”中的另外一句話:"不能讓特例特殊到開始破壞既定規(guī)則。"
從這兩個問題就能看出作者想要強調(diào)的是:「Python 風格 無處不在」。為了更好地理解 Python 實現(xiàn),最好了解 Python 的設(shè)計風格。
筆記傳送門:特殊方法
第二章
第二三四章主講 Python 數(shù)據(jù)結(jié)構(gòu)及其背后的實現(xiàn),而第二章主要講了可變類型與不可變類型的區(qū)別。
要想寫出準確、高效和地道的 Python 代碼,對標準庫里的序列類型的掌握是不可或缺的。數(shù)據(jù)結(jié)構(gòu)的產(chǎn)生就是為了滿足各種不同的需求,例如能讓用戶在不復制內(nèi)容的情況下操作同一個數(shù)組的不同切片的 memoryview,能高效處理矩陣、矢量等高級數(shù)值運算的 NumPy 和專為線性代數(shù)、數(shù)值積分和統(tǒng)計學而設(shè)計并基于 NumPy 的 SciPy。計算機科學家主要抽象了幾大數(shù)據(jù)類型:字典、數(shù)組、列表等,這些數(shù)據(jù)類型都有不同的使用環(huán)境,使用好這些工具能讓你事半功倍、節(jié)省不必要的消耗。
另外,在讀這本書的前幾天,我剛好在 Segmentfault 里面看到一個問題 python小白 問關(guān)于a+=a 和a=a+a的區(qū)別,當時看完答案還有點似懂非懂的感覺,而讀完這章我能完全理解其區(qū)別所在了。
擴展閱讀:problem-solving-with-algorithms-and-data-structure-using-python 中文版
筆記傳送門:序列構(gòu)成的數(shù)組
第三章
前一章提到了列表、元組這兩種序列,以及它們的生成器表達式。這一章則介紹了散列表的基本概念、其背后的算法和由散列表實現(xiàn)的數(shù)據(jù)類型:字典和集合。
- 由于字典是由散列表實現(xiàn)的,因此字典的鍵必須是可散列的。
- set 類型本身不是可散列的(因為 set 是可變的),但其元素必須可散列。(這也是為什么 list 不能作為字典鍵的原因)
- frozenset 是可散列的。
- 散列表的實現(xiàn)導致它實現(xiàn)的數(shù)據(jù)類型效率很高,但這是以犧牲控件的代價所帶來的。
"優(yōu)化往往是可維護性的對立面"
由于字典使用了散列表,而散列表又必須是稀疏的,這導致它在空間上的效率低下。舉例而言,如果你需要存放數(shù)量巨大的記錄,那么放在由元組或是具名元組構(gòu)成的列表中會是比較好的選擇;最好不要根據(jù) JSON 的風格,用由字典組成的列表來存放這些記錄。用元組取代字典就能節(jié)省空間的原因有兩個:其一是避免了散列表所耗費的空間,其二是無需把記錄中字段的名字在每個元素里都存一遍。
筆記傳送門:字典和集合
第四章
目前沒遇到過編碼問題,不看。
第五章
第五章的主題是:高階函數(shù)沒這么重要了。
先來一段吐槽:
Lundh 提出的 lambda 表達式重構(gòu)秘笈如果使用 lambda 表達式導致一段代碼難以理解,F(xiàn)redrik Lundh 建議像下面這樣重構(gòu)。
(1) 編寫注釋,說明 lambda 表達式的作用。
(2) 研究一會兒注釋,并找出一個名稱來概括注釋。
(3) 把 lambda 表達式轉(zhuǎn)換成 def 語句,使用那個名稱來定義函數(shù)。
(4) 刪除注釋。
摘自“Functional Programming HOWTO”
現(xiàn)在函數(shù)式編程十分流行,但 Python 獨特的語法使得 lambda、map、filter 和 reduce 這些函數(shù)沒這么重要了,因為我們有 sum、all 等歸約函數(shù),還有 sorted、min、max 和 functools 這樣的內(nèi)置的高階函數(shù)。
最后(5.10.2小節(jié))講了一個和函數(shù)柯里化(Currying)十分相像的概念——偏函數(shù)(Partial Application),這兩者概念其實不一樣。
筆記傳送門:一等函數(shù)
第六章
作者從策略模式開始,討論了一等函數(shù)在設(shè)計模式中的角色,并用一等函數(shù)簡化了設(shè)計模式的實現(xiàn)方式,以此來展示 Pythonic 的設(shè)計模式應該是什么樣子的。
筆記傳送門:使用一等函數(shù)實現(xiàn)設(shè)計模式
第七章
第七章介紹了裝飾器和閉包,作者給閉包下了一個清晰的定義:
閉包指延伸了作用域的函數(shù),其中包含函數(shù)定義體中引用、但是不在定義體中定義的非全局變量。函數(shù)是不是匿名的沒有關(guān)系,關(guān)鍵是它能訪問定義體之外定義的非全局變量。
作者用一個閉包實例和作用相同的類來比較,引出了自由變量(free variable)的概念,以此指出閉包與普通函數(shù)不一樣的地方——閉包會保留定義函數(shù)時存在的自由變量的綁定。在此之后,再引出可變類型與不可變類型對自由變量的影響,從而引出可能導致閉包失效的原因(第二章的主題:可變類型與不可變類型的區(qū)別),同時給出了解決辦法:nonlocal 聲明。
本章結(jié)尾的雜談提到了「一般來說,實現(xiàn)“裝飾器”模式時最好使用類表示裝飾器和要包裝的組件?!?,也就是通過實現(xiàn) __call__ 方法的類來實現(xiàn)裝飾器。遺憾的是本書只通過函數(shù)來解說裝飾器以助于理解,類裝飾器沒有提及多少。
筆記傳送門:函數(shù)裝飾器和閉包
第八章
不可變集合不變的是所含對象的標識。
第八章中,作者從「元組是不可變的,但是其中的值可以改變」引申到淺復制和深復制的區(qū)別。

淺復制帶來的影響可以參考 example(點 foward 顯示下一步)
作者還提到了兩個容易忽略的函數(shù)參數(shù)引用問題:
- 不要使用可變類型作為參數(shù)的默認值
- 防御可變參數(shù)
最后一節(jié)討論垃圾回收、del 命令,以及如何使用弱引用“記住”對象,而無需對象本身存在。
另外這章有意思的地方在于作者提到了一個常見的說法錯誤:「對引用式變量來說,說把變量分配給對象更合理,反過來說就有問題。畢竟對象在賦值之前就創(chuàng)建了?!?/p>
筆記傳送門:對象引用、可變性和垃圾回收
第九章
要構(gòu)建符合 Python 風格的對象,就要觀察真正的 Python 對象的行為。
——古老的中國諺語
第九章主要講如何編寫 Pythonic 的對象。作者從構(gòu)建一個 Vector 類型來介紹符合 Python 風格的類需要注意的地方,例如__repr__不要硬編碼類名、類屬性的私有化、格式規(guī)范微語言、散列化要注意的條件等。
作者還講了構(gòu)建一個可散列的類型所需要實現(xiàn)的條件:
- 正確的實現(xiàn)
__hash__和__eq__方法 - 不一定要實現(xiàn)只讀屬性,但是要保證實例的散列值絕不能變化。
類屬性用于為實例屬性提供默認值。Django 的類視圖也大量用到了這個特性。
個人十分喜歡名稱改寫(屬性的私有化)中的一張示意圖:
「避免意外訪問,但不能防止故意做錯事?!?,以此來提醒名稱改寫所實現(xiàn)的私有化自身的缺陷。

筆記傳送門:符合 Python 風格的對象
第十章
不要檢查它是不是鴨子、它的叫聲像不像鴨子、它的走路姿勢像不像鴨子,等等。具體檢查什么取決于你想使用語言的哪些行為。 (comp.lang.python,2000 年 7 月 26 日)
——Alex Martelli
其中介紹了鴨子類型,指忽略對象的真正類型,轉(zhuǎn)而關(guān)注對象有沒有實現(xiàn)所需的方法、簽名和語義。在 Python 中指免使用 isinstance 檢查對象的類型。
如果我想實現(xiàn)一個序列,可以實現(xiàn)__init__、__len__、__getitem__等一序列的方法,使其行為像序列,那么這就是一個序列,這也就是人們所稱的鴨子類型(duck typing)。
自己的理解:要明白自己希望的鴨子有哪些特性,只要我實現(xiàn)出來了,那么這就是鴨子。
Tips:
- 可以用
dir(slice)來查看序列的屬性 - 當 Python 庫文檔查詢不到方法的文檔的時候,可以嘗試用
help(slice.indices)來查詢。( 直接查詢__doc__屬性的信息 )
第四小節(jié)講可切片的序列需要關(guān)注的兩個問題:
如果創(chuàng)建的序列內(nèi)部由數(shù)組(或其他序列)實現(xiàn),那么就要考慮切片對象的實現(xiàn):切片返回的是自創(chuàng)建的序列對象 還是數(shù)組(或其他序列)?如果需要考慮,就是在
__getitem__方法里修改其實現(xiàn)方式。動態(tài)存取屬性,使序列能通過名稱訪問序列的屬性(v.x,v.y代替v[0],v[1])。也提到了實現(xiàn)
__getitem__時可能會產(chǎn)生的問題,和解決方法。
章節(jié)末尾的雜談提到了要遵循 KISS 原則(Keep it simple, stupid),不要過度設(shè)計協(xié)議。
筆記傳送門:序列的修改、散列和切片
第十一章
本章討論的話題是接口:從鴨子類型的代表特征動態(tài)協(xié)議,到使接口更明確、能驗證實現(xiàn)是否符合規(guī)定的抽象基類(Abstract Base Class,ABC)
我們可能不需要寫抽象基類,但是閱讀本章能夠教我們怎么閱讀標準庫和其他包中的抽象基類源碼。
其中,作者引用了 Alex Martelli 的一篇文章,用表型系統(tǒng)學(phenetics)和支序系統(tǒng)學(cladistics)用水禽來類比抽象基類。(⊙﹏⊙)b
其中有第十章提到的「鴨子類型」,還有以前沒提過的、描述一種新的 Python 編程風格的「白鵝類型」(goose typing)。
白鵝類型指,只要 cls 是抽象基類,即 cls 的元類是
abc.ABCMeta,就可以使用isinstance(obj, cls)。
對此,作者在章節(jié)小結(jié)里面提到:
借助「白鵝類型」,可以使用抽象基類明確聲明接口,而且類可以子類化抽象基類或使用抽象基類注冊(無需在繼承關(guān)系中確立靜態(tài)的強鏈接),宣稱它實現(xiàn)了某個接口。
本章最后還介紹了和 Go 語言協(xié)議的功能十分類似的 __subclasshook__ 方法。
筆記傳送門:接口:從協(xié)議到抽象基類
第十二章
分析 GUI 工具包 Tkhinter 的多重繼承,并且展開分析了多次繼承所帶來的「菱形問題」,以及 Python 對應的解決方案——方法解析順序(Method Resolution Order,MRO),最后作者給了八條關(guān)于處理多重繼承的建議。
9.5.1. Multiple Inheritance 里面提到了繼承順序是深度優(yōu)先從左至右不重復。
For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy.

筆記傳送門:繼承的優(yōu)缺點
第十三章
第十三章介紹了重載運算符的時候要考慮多重情況。
In the face of ambiguity, refuse the temptation to guess.
面對太多的可能,不要嘗試猜測。(ZoomQuiet禪譯)
——《The Zen of Python》
我們要嚴謹?shù)貙Υ赡軙霈F(xiàn)的操作數(shù)。
對于為什么需要重載運算符,在雜談中作者提到了對于一部分人來說,重載運算符是十分重要的,符合人類直覺的表示法十分重要,例如金融工作會接觸到一些由不同類型的參數(shù)(整數(shù)、或其他精度的數(shù)字)組成的公式。相比于不支持運算符重載的 Go 與 Java 語言,Python 采取了折中的方式,允許重載運算符,也有一些限制,如:不能重載內(nèi)置類型的運算符、不能新建運算符、一些運算符也不能重載(is、and、or、not)。
筆記傳送門:正確重載運算符
第十四章
作者分別介紹了生成器表達式和生成器函數(shù),并詳細地列舉了每個標準庫生成器函數(shù)的用法。
作者依然很注意用詞,生成器是 "yields or produces" 生成值,而不是 "returns" 返回值,這樣有助于理解生成器獲取結(jié)果的過程,因為生成器不是以「常規(guī)」方式返回值的。
筆記傳送門:可迭代的對象、迭代器和生成器
第十五章
介紹了 else 的三種用法與上下文管理器和 with 的作用,作者用__enter__、__exit__等方法手動地實現(xiàn)了一個上下文管理器,還介紹了 @contextmanager 作為另外一種更優(yōu)雅的實現(xiàn)上下文管理器的方法。其中 @contextmanager 的 yield 語句也引出了第十六章中協(xié)程的概念。
筆記傳送門:上下文管理器和else塊
第十六章
建議看第十六、十七、十八章之前先理解五個概念:線程、進程、協(xié)程、并發(fā)和并行。
自己參考了:
在本章中,作者介紹了如何構(gòu)建協(xié)程,和協(xié)程的一些使用場景,章節(jié)末尾,作者舉了一個離散事件仿真示例,說明如何使用生成器代替線程和回調(diào),實現(xiàn)并發(fā)。
在前些章節(jié)的基礎(chǔ)上,作者在這章提到 yield 可以看做是控制流程的方式,即 yield 能獲取值(.send(foo)),也能產(chǎn)出值(foo = yield),還能不獲取和產(chǎn)出值(yield 后沒有表達式)。因此,我們能用它來構(gòu)建協(xié)程。
不管數(shù)據(jù)如何流動,yield 都是一種流程控制工具,使用它可以實現(xiàn)協(xié)作式多任務(wù):協(xié)程可以把控制器讓步給中心調(diào)度程序,從而激活其他的協(xié)程。
除了調(diào)用 .send(...) 方法發(fā)送數(shù)據(jù),本章還介紹使用 yield from 結(jié)構(gòu)驅(qū)動的生成器函數(shù)。
擴展閱讀:
Python 中的進程、線程、協(xié)程、同步、異步、回調(diào)
筆記傳送門:協(xié)程
第十七章
并發(fā)是計算機科學中最難的概念之一(通常最好別去招惹它) 。
——David Beazley Python 教練和科學狂人
早期的計算機從單用戶操作系統(tǒng)(同一時間只能運行一個任務(wù))轉(zhuǎn)變成多任務(wù)操作系統(tǒng)(同一時間可以運行多個任務(wù)),又由于多任務(wù)操作系統(tǒng)中程序經(jīng)常搶奪系統(tǒng)資源而引發(fā)死鎖這種缺陷,在 20 世紀 60 年代,計算機科學家就開始探索并發(fā)編程的道路,并發(fā)指交替執(zhí)行多個任務(wù),解決的就是前面提到的多任務(wù)操作系統(tǒng)的缺陷。直到現(xiàn)在,很多編程語言都為并發(fā)提供了支持,其中包括原生支持并發(fā)的 Go 語言,和有相關(guān)模塊支持的 Python。
并發(fā)(concurrency)不是并行(parallelism)。并行是讓不同的代碼片段同時在不同的物理處理器上執(zhí)行。并行的關(guān)鍵是同時做很多事情,而并發(fā)是指同時管理很多事情,這些事情可能只做了一半就被暫停去做別的事情了。在很多情況下,并發(fā)的效果比并行好,因為操作系統(tǒng)和硬件的總資源一般很少,但能支持系統(tǒng)同時做很多事情。
——《Go 語言實戰(zhàn)》
future 指一種對象,表示異步執(zhí)行的操作。
在第十七章,作者用一個下載國旗圖片的例子來介紹網(wǎng)絡(luò)下載的三種風格:依序下載、concurrent.futures 模塊(ThreadPoolExecutor 和 ProcessPoolExecutor 類)實現(xiàn)的并發(fā)下載和 asyncio 包實現(xiàn)的并發(fā)下載。作者還介紹了阻塞性 I/O 和 GIL,最后介紹了如何借助 concurrent.futures.ProcessPoolExecutor 類使用多進程。
筆記傳送門:使用future處理并發(fā)
第十八章
并發(fā)是指一次處理多件事。
并行是指一次做多件事。
二者不同,但是有聯(lián)系。
一個關(guān)于結(jié)構(gòu),一個關(guān)于執(zhí)行。
并發(fā)用于制定方案,用來解決可能(但未必)并行的問題。
——Rob Pike Go 語言的創(chuàng)造者之一
第十八章中,作者主要介紹了新的并發(fā)編程方式,對比了 asyncio.Task (協(xié)程)對象與 threading.Thread (線程)對象的區(qū)別,包括 Python 包使用方式的區(qū)別和中斷時協(xié)程與線程的區(qū)別:鎖的保留。章節(jié)尾,作者介紹了 asyncio 包的使用和并發(fā)編程需要注意的地方。
筆記待補
第十九章
第十九章主要介紹了動態(tài)屬性編程。
>>> class Foo(object):
... pass
...
>>> foo = Foo()
>>> foo.a = 3
>>> Foo.b = property(lambda self: self.a + 1)
>>> foo.b
4
這就叫做動態(tài)屬性(dynamic attribute),不同于屬于靜態(tài)語言的 Java 需要依靠 setter 和 getter 方法,Python 能十分方便地設(shè)置屬性和讀取屬性。
作者拿 FrozenJSON 類做例子:把嵌套的字典和列表轉(zhuǎn)換成嵌套的 FrozenJSON 實例和實例列表。FrozenJSON 類的代碼展示了如何使用特殊的 __getattr__ 方法(處理屬性的函數(shù))在讀取屬性時即時轉(zhuǎn)換數(shù)據(jù)結(jié)構(gòu)。
作者還介紹了很多處理屬性的屬性和函數(shù)以及利用特性(@properties)來修改設(shè)置屬性和讀取屬性的方式。
筆記傳送門:動態(tài)屬性和特性
第二十章
有時候看書看著就忘了一些名詞是什么了,因此參考了下【譯】Python描述符指南,描述符類就是實現(xiàn)描述符協(xié)議的類。
相比于第十九章中利用特性(@properties)來修改屬性的存取邏輯,第二十章主要介紹了描述符——對多個屬性運用相同存取邏輯的一種方式。兩者的區(qū)別是特性有時更合適和簡單,而描述符更靈活。這章還介紹了覆蓋型與非覆蓋型描述符的對比,最后也給出了使用描述符的建議和優(yōu)缺點。
筆記傳送門:屬性描述符
第二十一章
(元類)是深奧的知識,99% 的用戶都無需關(guān)注。如果你想知道是否需要使用元類,我告訴你,不需要(真正需要使用元類的人確信他們需要,無需解釋原因) 。
——Tim Peters
Timsort 算法的發(fā)明者,活躍的 Python 貢獻者
上面是第二十一章的引言,我聽從這位傳奇開發(fā)者的建議,沒有看。
總結(jié)
整本書都在強調(diào)如何最大限度地利用 Python 標準庫以及講述 Python 背后的設(shè)計思想。身處眾多動態(tài)編程語言中間,Python 無疑是獨行獨立的,這也是為什么很多 Python 開發(fā)者驕傲地宣稱自己是一名 Pythonista。
自己只是不求甚解地通讀了一遍書,學到了很多,但書中仍有太多不熟悉的知識點。因為假期不多了,只能等日后二刷這本書。過一遍這本書最大的收獲莫過于在面對問題的時候,自己的工具箱又多了不少工具,即使這工具還不太「趁手」。其中感受最深的就是現(xiàn)在看一些 Segmentfault 或 StackOverflow 問題的答案的時候不再那么毫無頭緒,并開始試著從前輩們的角度思考問題。另外書中多次提到 Django 的一些實現(xiàn)方式,對自己日后讀源碼的時候有幫助。
倉促本身就是最要不得的態(tài)度。當你做某件事的時候,一旦想要求快,就表示你再也不關(guān)心它,而想去做別的事。
——羅伯特 · M · 波西格 《禪與摩托車維修藝術(shù)》
自己的確因為閱讀計劃的期限而讀的倉促了一些,這句話放到文尾,提醒自己在讀下一本書的時候,盡量做到靜下心來。