2008年11月29日

[讀書筆記] Python 核心編程 (Ch11~12)

第 11 章的 functional programming 算是比較特別的。下面以 functor 代稱 function object。

Chapter 11: Functions and Functional Programming

  • 函式無需宣告,定義時即宣告。開始執行函式時需已有定義。
  • 可用 default arguments、可做 recursion、可 nesting
  • functor 可以:供調用、做為函式參數、存入容器、被 assign ( by reference )。
  • documentation string:定義的開端的 unassigned string
  • function 若沒有給定 return value,就會隱式回傳 None
  • return 多個值時,就是把值塞在 tuple 裡回傳。
  • 可用 type() 來模擬靜態型別語言的 function overload
  • 用 keyword arguments 就可不按參數順序出牌。但還是需排在 positional arguments 後面。
  • 有 default argument 的 parameter 必須列在參數列尾端。
  • 在函式定義完成、有了 functor 之後,可以用 . 增加 function attribute
  • function / method decorators:以 functor 為參數及回傳值的 function。可用來修改被修飾的函式。用法:
    @deco1(args)
    @deco2
    def func(): pass

    等同於 func = deco1(args)(deco2(func))
  • Grouped variable-length arguments 的定義及呼叫語法:
    func(positional_args, keyword_args, *tuple_grp_args, **dict_grp_args)
    其中 informal nonkeyword argument 全被塞進 tuple,informal keyword argument 全被塞進 dictionary。
  • anonymous function:lambda [arg1[,arg2...]]: expr。回傳一個 functor。缺點係它是個 one-liner......。想完成更多事,可用它跑 tuple of functions。
  • functional programming BIFs:
    map(func, seq) 傳回 list of func(seq[N])
    map(func, seq1[,seq2...]) 傳回 list of tuples(func(seq1[N]), func(seq2[N]),...)
    reduce(func, seq[,init]) 以雙參數的 func 求出 ...func(func(func(init, seq[0]), seq[1]), seq[2])... 的結果值。
  • currying 泛化而來的 partial function application,可由 functools module 的 partial 創建。partial(func, args) 傳回 func(args, ...) 這樣已固定某些參數的偏特化 functor。
  • variable scope 的規則:對 identifier name 的搜尋由 local scope 到 global scope。
  • 以 global 修飾變數,可引用已命名的 global variable。在 Python 3.0 的 nonlocal 出現前,對於 outer scope variable 只能取值而沒辦法賦值 ( assignment 會產生出新的 local variable )。
  • closures:「只使用到自身及 outer functions 的變數們、而未用 global variable」的 inner function。據說用途強大廣泛......
  • 關於 generator:PEP 255 & PEP 342。含有 yield 的 function 便是 generator function。呼叫它可返回 generator object 。
  • 可對 generator object 調用 next() 傳回 yield、send() 塞給 yield、close()。next() 失敗時丟出 StopIteration 異常。

Chapter 12: Modules

  • import module [as alias] 之後使用 alias.name 會指涉到 module 內的本尊。
  • from module import name 讓之後使用 name 時不必再加前綴 module. 修飾。name 進入本區 namespace,只會被修改到副本而不會影響原 module 內的。
  • module 僅在第一次被導入時,被加載並執行
  • import 時會依 sys.path 給的 path list 尋找並導入第一個找到的。導入的 module 的作用域同 import 所在處。
  • sys.modules 傳回已導入的 {ModuleName:path} dictionary
  • 3 個 namespaces:built-ins、global 以及隨著函式調用而不斷變化的 local
  • BIFS:globals() / locals() 回傳該域內所有名稱及其值的字典。reload(module) 可重新載入並執行 module。

2008年11月28日

[讀書筆記] Python 核心編程 (Ch8~10)

第 8 章分支與迴圈 / 第 9 章檔案與 I/O / 第 10 章錯誤與異常。

一路看下來,Python 確實是個進化中的語言;新的特性不斷導入,舊的特性與過時語法慢慢淡出,一代後浪推前浪......

Chapter 8: Conditionals and Loops

  • if、while、break、continue 都沒啥特別的 =3=
  • 用 dictionary 查詢會比一狗票 elif 的效率還好。
  • C/C++ 的三元運算子 C? T: F 的 Python 寫法是 T if C else F
  • 強大的 for 可以捅 iterable object 並自動調用 next()、處理 StopIteration 異常。搭配 range(start, end, step) 服用也不錯。對於巨大的迭代範圍,xrange() 可以迴避 range() 產生完整 list 的開銷。
  • pass 用來表示 No OPeration。
  • else 還可用來搭配 for、while 做 post-processing:如果迴圈正常完成而非被 break 掉,就跑進 else。
  • 對於許多型別,Python 都會自動迭代它。例如 for eachLine in File、for eachKey in Dict 等。底下運作的 iterator,factory function 為 iter()。
  • 迭代過程中,別改變迭代對象的內容。
  • List comprehensions,來自 Haskell 的激強大工具。結合了 map()、lambda 與 filter(),省心至極。
  • Generator expression 與 list comps 類似,返回 generator 供每次計算後將條目 yield 出來。Lazy evaluation 讓它迴避了 list comps 需產生所有物件的記憶體消耗。
  • 所以,當只需迭代一次時用 generator expr;需迭代多次或是想使用 result list 的話就用 list comp。對於小型、中型的資料量,兩者的效率差異不大。

Chapter 9: Files and Input/Output

  • 抽象的 file-like object:用通用接口完成資料結構的 I/O。例如讀寫檔案、打開 URL 並讀取頁面等。
  • 用 open(path, mode) 或 file(path, mode) 都可開啟文件。開啟模式同 C 的 fopen:r 讀、w 寫、+ 讀寫、a 追加寫入、b 二進位、U 讀取時用 UNS。預設值 r。
  • readline() 讀取單行及 \n,readlines() 讀取剩餘所有行。writelines() 不會自動加入 \n
  • os module 中的有用屬性:linesep 換行符、sep 路徑分隔符、pathsep 路徑們的分隔符、curdir 目前目錄、pardir 父目錄。當然還有很多很好很強大的功能......
  • print 不加逗號的話,就會自動附加換行符。
  • 程式一執行就可以動用的三個文件:stdin、stdout、stderr。可從 sys module 取用之。
  • 同 C,sys.argv[0] 為程式名稱,len(sys.argv) 即 argc。協助處理參數列的 module 有 getopt 和 optparse。
  • 協助永久儲存數據 ( 字串、Python 物件 )的 module:marshal、pickle、shelve 等。

Chapter 10: Errors and Exceptions

  • try-except:try 區塊出錯時直接跳下來從 except 找對應的異常類別並執行;之後接續 except 後面的語句執行。tuple of exceptions 可對應多個異常。額外參數為 exception class 的 instance,可能提供更詳細的錯誤報告。
  • 所有異常皆繼承自 BaseException,可對應所有類型的異常。除去 KeyboardInterrupt 及 SystemExit 的異常類別為 Exception。
  • try-except-else:同迴圈,try 沒有發生異常則進入 else。
  • finally:無論 try 是否發生 / 捕捉到異常,皆會執行 ( 在 try 裡 return 掉也是 )。try-finally 在 try 出異常時直接跳進 finally,執行完再丟出異常。若由 finally 本身發出異常或 return、break、continue 則原先的異常會蒸發。
  • try-(try-except-else-finally)-except......
  • with 只能與支援 context management protocol 的 object 協同工作。with open('file', 'r') as f: 開啟檔案為 f 並在區塊中產生異常時依然能自動關閉檔案。
  • Section 10.4.2 講 Context Management Protocol。有需要時再回頭翻 =3=
  • raise ExClass, args:觸發一個異常,為 ExClass 的 instance,以及塞進去的參數。
  • assert expr[,args] 可假想為 raise-if-not,丟出 AssertionError 異常。
  • 內建的 standard exceptions 在程式開始前就被載入了。
  • Section 10.9 講述如何繼承並創建自訂的異常,有個百餘行的範例碼 =.=
  • sys.exc_info() 回傳 (exc_type, exc_value, exc_traceback)
  • Exception handling 使程式更正確、成熟、穩固。
  • 提供異常處理機制,是為了讓程式員易於追蹤潛在錯誤,並做出相應處理。盡量克制 except,不要 try 一大塊程式碼並 except Exception 然後直接忽略掉。

2008年11月26日

[讀書筆記] Python 核心編程 (Ch6~7)

繼續洗版。

這兩章講 sequences 和容器,可以體會到 dynamic typing 的靈活之處。最複雜的部份是深淺拷貝的差異...... 可能得食個幾次虧才能記住吧 =.=

Chapter 6: Sequences

  • sequences ( 序列型別 string、list、tuple ) 的一大特色是 iterable。
  • 對 sequence 取元素 s[-i] 會得到 s[len(s)-i]
  • slice 是常用的操作,如 s[start:end:-1] 可得 [start, end) 範圍逆序後的結果。slice 時不會受到 index 的上下限限制。
  • 一些可對 iterable object 操作的 Built-in functions:
    enumerate(iter) 傳回迭代對象的 (index, item) tuple。
    zip([item1, item2..., itemN]) 傳回 list of tuples,其中第 n 個 tuple 為 itemX[n] 的集合。
    其它還有像 len(iter)、cmp(iter1, iter2)、max(iter)、min(iter)、sum(iter)、sorted(iter)、reversed(iter) 等。
  • 對於 container type 可用 in / not in 測試元素是否存在。字串也可用這種方式檢測子字串存在性。

Strings

  • immutable
  • Python 沒有單一字元型別,只有字串。字串不是容器。
  • 標示字串的雙引號和單引號沒有區別,成對出現就好。
  • str.join() 的效率較 + 好 ( 由於 immutable,對於 + 產生的新字串,需要另外分配新的記憶體容納 )。
  • 格式化輸出,支援 C 的 printf 的各式參數 ( %0d %3.2f %x %e %E 等 )。可用 value tuple 或 dict{ID:value} 兩種型式。更精細的控制,見書中 Section 6.4。
  • print(r'\n') 得 '\\n'。這特性拿來配 regex 可有效降低抓狂機率。
  • regex 引擎支援 ur'unicode\n' 這樣的字串。( 一起使用時,u 必須出現在 r 前面。)
  • 三引號表示的字串可以包含換行、tab 等字元。
  • 字串不會自動包含 C 風格的 NULL,而且 Python 也不依靠 NULL 判定結尾。計算字串長度時可省心一些。
  • input = raw_input(s) 印出 s 並將用戶輸入結果存入 input。丟一個在腳本結尾可避免執行完直接蒸發。
  • chr(65) 和 ord('a') 分別傳回 'A' 和 97。還有 unichr() 可返回 UCS2/4 的結果。
  • Section 6.6 是一大票 String built-in methods,有需要再回去翻吧 =3=。這些 BIMs 可和 unicode 合作愉快。要注意字串是 immutable 的就是。
  • 由於 immutable,字串做 assignment 時,lvalue 只能是整個 str object 而不能是 str 的一部份。rvalue 則無此限制。
  • 確保字串能正確處理 Unicode 所需做的事:字串以 u 為前綴、以 unicode() 代替 str()、在即將寫出 / 剛讀入時才 encode / decode。

Lists

  • mutable container
  • += 和 list.extend() 有同樣功效。
  • + 的兩個運算元必需有一樣的型別。list.append() 和 list.extend() 可以避開限制。
  • list.sort() 排序並返回 None。sorted(List) 返回排完序的列表並且不會改變 List。
  • Section 6.15 給了以 list 實作 stack 和 queue 的例子,其中用到 dictionary 搞 function pointer...... 激方便呢 (||。3。)

Tuples

  • immutable container。好處?當成參數丟進 function 時可以保證不被改變。
  • 大多數操作和 list 一樣。
  • 創建單元素的 tuple 時,要加個逗號,以避免小括號被當成語意邏輯分割用。
  • tuple 包含的元素保有自己的 immutability。例如 tuple 中包含的 list 元素還是可以被修改。

Shallow & Deep Copies

  • shallow copy:創建新的 object,但是其內容還是原物件的 reference。
  • deep copy 就真的會摳一份新的、獨立的 reference 過去。
  • 對於 mutable type ( list、dictionary... ),assignment operation 會做 shallow copy ( 以 rvalue 的 reference 賦予 lvalue )。
  • 這表示當我在盒子上亂塗鴉的話,你也衰洨......
  • immutable type 就沒有這種困擾了。我會去撿個畫好的新盒子回來,你的還是亮白如新。
  • copy module 的 copy.copy() 做 shallow copy;copy.deepcopy() 做 deep copy。
  • 由某方面來說,mutable type 可以當做共享的 C++ static variable
  • 這特性實在令人激困惑......

Chapter 7: Mapping and Set Types

Dictionaries

  • mutable container。實現 key → value 的映射。
  • key 的排列是無序的,且 key 需為 hashable value ( hash(obj) 返回整數而非 TypeError )。Python 由這個 hash value 決定映射的目標位址。
  • 數值、字串等 immutable type 皆 hashable。tuple 若只含 immutable 元素則也為 hashable。
  • 重複賦值給 key 會把先前映射的 value 刷新。
  • BIMs:keys()、values()、傳回 list of tuple(key, value) 的 items(),搭配 for 頗好使。還有 update(dict2)、pop(key)、copy() 等。copy() 傳回 shallow copy,比用 factory function 複製的效率高。sorted(dict) 傳回對 key 排過序的字典。

Sets

  • set elements 為無序的 hashable value。
  • 有 mutable 的 set 與 immutable 的 frozenset 兩種。
  • set 只能由 factory function set()frozenset() 產生。
  • 運算子:< 子集、> 超集、| 聯集、& 交集、-- 差集、^ 互斥。產生的集合類型與運算子左邊的集合相同。
  • BIMs 與 dictionary 類似。另外有 discard(obj)、add(obj) 等。

2008年11月24日

[讀書筆記] Python 核心編程 (Ch1~5)

洗版文,第二版「Core Python Programming」及其簡中版「Python 核心編程」的讀書筆記流水帳。總算定下心開始啃蛇文本瞭......

本書主要是針對 Python 2.5 所寫;至於 Python 3.0 的新特性,可以看 Python 官方的 What’s New In Python 3.0

以下不保證筆記內容的正確性。

前四章算是 Introduction,快速掃過一些 Python 的特色與特性。第五章來插花的,數值類型,沒啥難度。

那麼,開始洗版吧 (>ω<)♪♪

Chapter 1 ~ 4

  • Case sensitive
  • Python Enhancement Proposal 8 是重要的 Python code 風格指南。
  • import this 可印出 The Zen of Python
  • Everything in Python is an object.
  • variable 在第一次被 assign 時自動宣告,且為 dynamic typing。
  • 基本運算元和 C 類似,支援 bitwise operator 和 +=、*= 等,但不支援 ++、- - ( 會以 unary operator 處理 )。
  • 可以使用 2 < 3 < 4 != 5 這樣的述句,由多個隱式 and 連接。
  • andor 有 short-circuit evaluation。
  • 連續程式碼換行的方法:backslash \、連續字串之間 ( 自動串接 )、三引號的跨行字串、小中大括號之間 () [] {}。
  • 基本的分支:if elif else。想用其它語言 switch 那樣的功能,可以把測試值們塞進 list 並用 for 跑它。
  • 基本的迴圈:for while
  • 基本的資料結構:immutable 的 str 和 tuple,以及 mutable 的 list 和 dict。slice 所產生副本其 mutability 也與原先的相同。
  • immutable 是為了效率考量。數字型別也是 immutable 的,i = i + 1 會令 i 指向另一個 object。
  • Python 3.0 的 string 將會全部 unicode 化。
  • 函式定義時可給 default arguments。沒有給定 return value 的函式,會自動返回 None。
  • assignment statement 不會傳回值,但可以 chain。
  • variable 的 reference count 降到 0 或發生無意義的循環引用時,會被 garbage collector 清掉。
  • 增加變數引用計數的方式如:賦值、做為函式參數、容器元素等。trace / debug 時也會增加 object 的引用數。
  • 減少引用計數:離開 scope、原變量名被賦予其它 reference、del statement、從容器 remove 等。
  • 在 Python 的 object 模型中,每個 object 都像一個盒子,引用計數如上面貼的標籤。標籤被撕光的無主物,就會被丟進拉雞車。
  • module 被 import 時,__name__ 的值為 module name。若 module 被直接執行,__name__ 為 "__main__"。
  • 對於 mutable 型別,function argument 以 pass by reference 方式傳遞。immutable type 則是 pass by value。
  • 用 local variable 取代 module variable 除了方便性考量以外,還可以提升性能。
  • print 會自動換行。加個逗號可以扼止這項悲劇。一次丟一堆參數給 print 會在之間自動加入空格。更精細的排版可以用 "%s%d%f" % (str, 10, 3.0) 這樣的方式控制。
  • Python 3.0 中的 print 會全面改為 function 型式以提供更多功能。
  • None、值為 0 的數字、empty container 的 boolean value 都是 False (0)。
  • type 是 Python 所有 class 的 metaclass。
  • == 測試 value equality,而 is 則測試 memorywise equality。
    a is b 等同於 id(a) == id(b)
    例如:print(True is 1) 得到 False
    print(True == 1) 得到 True
    可能的話使用 is 可迴避求值過程的開銷。
  • repr(obj) 取得 obj 的代表字串,適合給 python 看。
    str(obj) 取得 obj 的可讀性較佳的字串,適合給人看 ( print 對物件調用這個函式 )。
    通常 obj == eval(repr(obj)) 是成立的。
  • 有事沒事可以 help(obj) 一下。

Chapter 5: Numbers

  • 數值型別包括整數 int、無限位長整數 long、雙精度 float、複數 complex。摻在一起運算時會自動晉級。
  • int 和 long 未來將合併,不必再煩惱其區別和整數溢位瞭。
  • decimal module 中的 Decimal 可用來表示精確的十進制小數,以免被 IEEE 754 痛整。
  • 目前以運算符 / 對 int 做除法會執行 floor division;未來將改為 real quotient。
  • 運算符 // 總是做 floor division ( 包括對 float 型別也是 )。