英文版Dive in python可以在下面找到中文翻譯http://linuxtoy.org/docs/dip/toc/index.html
3.1 模組
模組的__name__,當模組被import時,其為模組的名字,當模組作為main執行的時候,其為__main__
3.2 dictionary
dictionary中的key-value對可是任何類型的,同一詞典中,可以混用匹配。
詞典的key是大小寫敏感的,並且要求是常量類型。可以使用del dic[key]來刪除一個元素。
items()返回一個list,其中的元素為二元的tuple,t[0]為key,t[1]=val
3.3 List
List也支援重載+操作,用於將兩個list串連起來,並返回一個List,因此它沒有extended執行高效。list也支援+=操作來串連兩個list。
list的append()操作將一項元素加入到list的末尾,如果想要串連兩個list,應該使用extend而不是append.
*可以作用於list,作為重複器。
list在引用[]中可以接兩種slice對象,一種是[start:end:step],一種為[sliece(start,end,step)]操作返回的slice
內建操作range(start,end,step)返回一個list。
3.4 Tuple
Tuple不能向其增加,刪除元素,以及返回索引這樣的函數,但有in。可以認為Tuple本身是不可變的,因此可以作為dictionary的key。
Tuple和List可以互相顯式的進行轉換,對內容進行凍結或解凍。tuple可以看作是C中的enum類型。其中元素不可改變,而且是可隨機訪的。變數按位置得到一個整數值。
變數使用時不需要先聲明其類型,但所使用的變數必須之前經過定義。
python支援一次給多個變數賦值,如t=(1,2,3) (x,y,z)=t。
3.5 格式化字串
與C中sprintf一樣的用法類似,print "%s,/t %d" %(str, 10)
當定義一個只包含一個元素的
tuple 時逗號是必須的。如果省略逗號,Python
不會知道 (userCount)
究竟是一個只包含一個元素的 tuple 還是變數 userCount
的值。
t = (1) //type(t) ==> int
t = (1,) //type(t) ==> tuple
3.6 映射list
使用[],通過對lista中第個元素應用一個函數,從而產生另一個list。如[expression for elem in list1]
將一個list的映射交給自己是安全的。
4.5 過濾List
如果在是[ express for elem in list1 if if_express ],以if開頭的稱之謂過濾運算式。在python中,過濾運算式返回為真時,元素才會加入到映射list中。
3.7 基於字元的list中元素的串連與分割
"delem".join(list1) 將list中的字元按delem符號分割然後串連成一個字串。
相反的操作可以在字串上調用split("delem",cnt),它將對一個str,按delem進行分割cnt次,把元素放入list中並返回這個list;
有用的技巧是" "
.join(string.split()),它去除string中的多餘空格,再使用單個空格將它們格式化連起來。
4.2 函數
python中的函數參數列表可以看作是一個詞典,參數可以不按定義的順序進行傳遞,但此時需要顯式的指定參數名稱。
str和type可以接受任何類型的對象,前者返回其str,後者返回其類型。這些內建函數都包含在__builtin__中。
getattr(obj,'name' [,default]) 返回obj上名稱為name的屬性引用。這個函數可以作用於任何對象,返回方法引用或資料引用。
4.6 邏輯運算式 and/or
使用 and
時,在布爾環境中從左至右演算運算式的值,會一直計算直到返回假,此時返回這個假的對象,否則返回最後一個(真)對象。
0
、''
、[]
、()
、{}
、None
在布爾環境中為假;其它任何東西都為真。
使用 or
時,在布爾環境中從左至右演算值,就像 and
一樣。如果有一個值為真,or
立刻返回該值。否則返回最後一個(假)對象。
and-or
技巧,也就是 bool
and a
or b
運算式,當 a
在布爾環境中的值為假時,不會像 C
語言運算式 bool
? a
: b
那樣工作。a為真時,可以像C中的三目運算式。安全的使用方法為 (1 and [a] or [b])[0]
4.7 Lambda運算式
python中只能定義單行函數。但它可以接受多個參數,任何使用lambda函數的地方都可以使用普通函數封閉,而且沒有複雜度限制。
5.2 對象匯入
模組對象
import module 不會使得module下面的方法可見,如果要使用其下的方法,需要使用module.method來引用。如果要經常使用,可以用from module import method來使method可見。盡量少要from module import *
5.3 類
如果在類中定義了__init__,並且你的類繼承了其它類,那麼你需要在__init__()中顯式的調用基類的__init()函數。__init__()雖然不能稱之謂建構函式,但它承擔了一個對象在構造後的初始化工作,當你需要一個類的對象執行個體時,你需要調用類,並傳入在__init__()定義的參數。
類的資料成員可以在首次定義時突然加入類中,並可以動態加入和刪除。與C++不同的是,在類的內部,我們要引用資料或方法成員時,需要顯式的指定self(類似於this指標)。
每個類都有一個內建屬性__module__,它用來說明對象所屬的模組。
5.6 專用類方法
在類中以__*__形式的一些內建函數,它由類自己定義,並在合適的時候由python的外部函數調用,例如每個類可以定義自己的__str__(),當內建函數str()作用在一個類上時,這個類的__str__()將被調用。這些稱之為類型的自我表達能力。
在python中查看兩個對象的同一性用is,查看兩個對象是否相等用==
5.8 類屬性
類的對象由屬性__class__標識其所屬的類,我們可以通過它類比C++類中的靜態變數。python中沒有私人變數,但所有以__開頭的變數會被mangle名稱,導致在外部不可見。
5.9 私人函數
如果一個 Python
函數,類方法,或屬性的名字以兩個底線開始
(但不是結束),它是私人的;其它所有的都是公有的。
Python
沒有類方法保護
的概念 (只能用於它們自已的類和子類中)。類方法或者是私人
(只能在它們自已的類中使用) 或者是公有 (任何地方都可使用)。
6.1 異常處理
如果使用一個具有層次的異常處理邏輯,當異常沒有發生時,可以使用else來處理層次邏輯。
6.2 檔案操作
標準內建函數有open() seek() tell() read() write() close()
6.3 路徑與目錄操作
在os.path中的函數有split() splitext(),join()等工具
在os中,有操作isfile(), isdir(),chdir(),fchdir(),getcwd(),fdopen(),popen(),dup(),fstat()等
7.1 Regex
- ^
匹配字串的開始。
- $
匹配字串的結尾。
- /b
匹配一個單詞的邊界。
- /d
匹配任一數字。
- /D
匹配任意非數字字元。
- x?
匹配一個可選的 x
字元 (換言之,它匹配 1 次或者 0 次 x
字元)。
- x*
匹配0次或者多次 x
字元。
- x+
匹配1次或者多次 x
字元。
- x{n,m}
匹配 x
字元,至少 n
次,至多 m
次。
- (a|b|c)
要麼匹配 a
,要麼匹配 b
,要麼匹配 c
。
- (x)
一般情況下表示一個記憶組 (remembered group)
。你可以利用 re.search
函數返回對象的 groups()
函數擷取它的值。
PythonRegexHowTo
8 html處理
html的基本知識
8.5 命名空間
locals()返回局部命名空間中的變數,dict形式,但其為複本,修改這個字典不會改變局部命名空間中的變數值。globals()返回全域命名空間中的變數,dict形式,其為引用,修改這個字典將改變全域命名空間中的變數值。
在一個Python程式的任何地方都有幾個命名空間,局部,全域,內建。對名稱的尋找也按上這個順序進行。
局部命名空間:函數或類的方法中。
全域命名空間:特指當前模組中
內建命名空間:對任何模組都可見的。
8.6 基於字典的字串格式化
採用如下的形式 dict = {key1:value1, key2:value2, ...} " we can see key1's value is %(key1)s "
8.8 SGMLlib中SGMLParser的工作原理
SGMLParser中定義了如何處理標記語言的方法,使用者通過繼承此類並定義類似於start_a() end_a()這樣的函數,當解析器遇到標記<a>和</a>時會查看使用者是否定義了相應的處理函數,如果定義了,則調用使用者函數來進行操作。否則則調用unkonw_starttag(),unknown_endtag()來處理,使用者可以重載這些函數來定義自己想要操作。
8.9 動態python
python可以通過字串,在啟動並執行時候得到相應的屬性及類或者執行個體,對於屬性可以通過getattr(),對於命名空間中的類可以直接通過str類型的名字在globals()返回的字典中查到。
9 XML處理
9.2 包的概念
可以認為最基本模組就是.py檔案,一個包就是一個目錄。包可以嵌套,被嵌套的包或者被包含的模組可以通過 "."來取得。包可以被匯入成為一個模組,這是通過包目錄下的__init__.py檔案中定義的匯入名稱做到的。包的目錄下必須包含__init__.py檔案,它可以為空白,但必須存在,否則此目錄不被識別為包並匯入其內部模組。
9.3 處理XML的介面
xmldoc = dom.parse()
root = xmldoc.childNodes[0]
需要注意的是,在根下面的子結點,標籤之間有硬斷行符號作為子結點分隔。資料在葉子結點之下,通過childNodes[0].data 取到。
通過這兩個介面即可以對簡單的XML檔案進行遍曆。任何結點都有方法toxml()及屬性 childNodes。
每個結點可以有屬性和文本,通過attributes或data可以進行訪問,attributes返回一個字典,裡面屬性的索引值對。分別可以通過keys()和values()獲得。
9.4 字元編碼
環境中的編碼,通過 sys.getdefaultencoding()或sys.setdefaultencoding()來擷取或指定。對於每個檔案 #-*- coding : UTF-8 -*-
9.5 搜尋XML文檔
通過getElementsNameByTagName()可以返回一組具有相同標籤名的子樹。順序遍曆返回的val[i]即可
10 指令碼和流
10.1 file-like對象
特指所有支援read(size = none)操作的對象,Python中定義了許多函數可以直接操作file-like對象,而不用使用者顯式的調用file-like對象的read和close 操作,如xml.minidom.parse()函數。
10.2 輸入輸出重新導向
通過儲存及改寫sys.stdout,sys.stdin,sys.stderr為其它檔案檔案對象即可實現輸入輸出的重新導向。為了不用指定一個檔案 (例如 binary.xml
),你需要指定“-
”,它會使得你的指令碼從標準輸入載入指令碼,而不是從磁
盤上的特定檔案。
10.3 處理命令列參數
可以使用sys.argv以及getopt模組。
import getopt<br />def test_getopt(argv=None):<br /> if argv==None:<br /> print("error")<br /> return<br /> opts,args = getopt.getopt(argv,"hp:d:",["help","port","dst"])<br /> print(opts)<br /> print(args)<br /> for opt,arg in opts:<br /> if opt in ('-h','--help'):<br /> print("user need help")<br /> elif opt in ('-p','--port'):<br /> print('port is %s'%arg)<br /> elif opt in ('-d','--dst'):<br /> print('dst is %s'%arg)<br /> else:<br /> break<br />str = '-h -p 80 -d 192.168.1.1 "c:/boot.ini"'<br />if __name__ == "__main__":<br /> test_getopt(str.split())<br /> test_getopt()<br />#output is followed<br />#[('-h', ''), ('-p', '80'), ('-d', '192.168.1.1')]<br />#['"c:/boot.ini"']<br />#user need help<br />#port is 80<br />#dst is 192.168.1.1<br />#error<br />#
11 處理HTTP
在python 3中,將htmllib刪除,相應功能移入urllib中。
http的規範可以參考RFC2616 http1.1的協議規範
12 SOAP
12.1 WSDL
WSDL是一種網路服務描述的規範,它由XML寫成,這樣一個服務可以被機器自動識別並處理,而不需要程式員去處理由WSDL描述的服務。此外不同企業可以通過UDDI將發布的各種服務整合起來,從而完成更大的工作流程。
相關WSDL與UDDI的資訊可以參考這裡
12.2 SOAP
SOAP基於WSDL中描述的服務,使用HTTP協議在網路不同節點間傳遞和接收訊息,可以完成RPC的功能。這樣使用者使用WSDL獲得網路上服務描述,由機器解析WSDL並得出如何使用服務,使用SOAP將服務調用訊息發送給服務描述中給出的伺服器。伺服器處理收到的XML文檔,完成相關的功能,然後採用SOAP將結果傳送回來。使高層使用者不需要關注服務的具體細節,提高工作效率。
13 單元測試
13.1 重要性
單元測試是以測試為核心開發策略的重要組成部分。如果你要寫單元測試代碼,儘早 (最好是在被測試代碼開發之前)
開發並根據代碼開發和需求的變化不斷更新是很重要的。單元測試不能取代更高層面的功能和系統測試,但在開發的每個階段都很重要:
- 代碼開發之前,強迫你以有效方式考慮需求的細節。
- 代碼開發中,防止過度開發。通過了所有測試案例,程式的開發就完成了。
- 重構代碼時,確保新版和舊版功能一致。
- 維護代碼時,當你的代碼更改導致別人代碼出問題時幫你留住面子。(“但
是先生
,我檢入 (check in)
代碼時所有的單元測試都通過了……
”)
- 在團隊開發時,可以使你有信心,保證自己提交的代碼不會破壞其他人的代碼,因為你可以
先運行其他人的單元測試代碼。(我在“代碼風暴”中見過這種事情。一個團隊將任務拆分,每個人都根據自己那部分的需求開發單元測試,然後與其他成員共用。
沒有人會出太大的偏差而導致代碼無法整合。
13.4 測試案例的要求
一個測試案例應該做到:
- 完全獨立運行,不需要人工輸入。單元測試應該是自動的。
- 可以自己判斷被測試函數是通過還是失敗,不需要人工幹預結果。
- 獨立運行,可以與其他測試案例隔離 (儘管它們可能測試著同一個函數)。每個測試案例是一個孤島。
13.5 測試案例的分類
正面測試案例:對於所有有效輸入,必須保證正確的輸出
負面測試案例:對於所有無效的輸入,必須保證正確的處理,負面測試案例分為:類型,範圍
完備性測試: 輸入輸出的模式是否有效
更多關於測試架構的內容請參見:Python單元測試架構說明
14 測試先行的開發
15 重構
16 函數編程
16.5 資料中心思想編程
使用map,filter這類函數,可以使用程式員不需要去使用for來處理過程的每一步,使程式員只需要關注如何處理資料。
16.6 模組的動態匯入
藉助於__import__('module'),程式員可以動態匯入以字串形式給出的模組名稱。
17 動態函數
17.7 yield產生器
yield產生器必須在函數內部使用,使用了yield的函數稱為generator函數,yield可以使用此generator函數每次調用next()時都返回一個值,直到其返回對象變得不可迭代。為了說明yield的工作過程,可以看下面的代碼
def generator():<br /> x=1<br /> while 1:<br /> yield x<br /> x+=1<br />gen=generator()<br />for i in range(10):<br /> print gen.next()
當我們聲明一個產生器gen時,函數並沒有被調用執行,直到我們第一次調用next()才使得yield返回函數內部x的值1,隨後函數停頓在yield語句上,直到下一次next()調用再返回x的值。如果通過for來訪問產生器,可以很方便,下面是一個例子。當然yield可以返回你想返回的任何對象。
def fibonacci(max):<br /> a, b = 0, 1<br /> while a < max:<br /> yield a<br /> a, b = b, a+b<br />for i in fibonacci(1000):<br /> print i
使用動態函數以及產生器,可以使你的代碼抽象度更高,你可以在使用中根據外部規則動態產生需要的各種函數,保持代碼的高度抽象和簡潔。
18 效能最佳化
18.2 Python的效能測試架構
Python內建了時間測試架構,只需要匯入timeit模組即可以方便的進行效能測試。首先需要產生一個Timer對象,它需要兩個參數,均為字串,前者為測試的函數後者為需要匯入的模組名。注意:被測代碼需要與記時代碼位於不同模組,並給出顯式的匯入指令。隨後便可以通過此對象進行時間測量。有兩個方法timeit()和repeat()