《Python核心編程》筆記(二)
今次的內容主要為字典、集合、迭代器、列表解析、生成器表達式和檢測與處理異常這幾部分內容,中間抑或摻加一些文件方面的內容。
注:本書為第二版,其中python的代碼主要為2.x版本,使用python3.x的朋友請留意。
字典
另類創建字典之方法
代碼示例:
1 | fdict = dict((['x',1],['y',2])) |
另類字典遍歷之方法
代碼示例:
1 | dict2['name'] = 'venus' |
刪除字典元素和字典
代碼示例:
1 | del dict2['name'] #刪除鍵為'name'的條目 |
字典比較之方法
簡單來說字典的比較算法會按照如下的順序進行:
- 比較字典長度,長者為大
- 比較字典的鍵,鍵比較的順序與keys()方法返回鍵的順序相同
- 比較字典中相同鍵的值
下面這個原理圖解釋了這一算法:
字典的工廠函數dict()
代碼示例:
1 | dict(zip(('x', 'y'),(1, 2))) |
如果輸入的參數是另一個映射對象,比如一個字典對象,對其調用dict()會從存在的字典裡複製內容來生成新的字典。新生成的字典是原來字典對象的淺複製版本,它與用字典的內建方法copy()生成的字典對象是一樣的,不過其速度比copy方法要慢。
代碼示例:
1 | dict(x=1, y=2) |
keys方法可以返回字典所有的鍵,但是是沒有順序的,如果我們希望對其進行排序,可以這麼做:
代碼示例:
1 | for eachKey in sorted(dict2): |
update()可以用來將一個字典的內容添加到另外一個字典中。字典中原有的鍵如果與新添加的鍵重複,那麼重複鍵所對應的原有條目的值將被新鍵所對應的值所覆蓋。
所有不可變的類型都是可哈希的,因此它們都可以作為字典的鍵。注:值相同的數字表示相同的鍵,即1和1.0的哈希值是相同的。另外,若元組中包含列表,則該元組不可作為字典的鍵。
集合
集合創建
代碼示例:
1 | set('cheeseshop') s = |
集合更新
s.add(‘z’), s.update(‘pypi’), s.remove(‘z’), s -= set(‘pypi’)
集合支持比較大小的運算,其含義與子集、超集之概念相同。
集合運算
- 聯合(並集) s | t
- 交集 s & t
- 差集 s - t
- 異或 s ^ t
注:若左右操作數類型不同(即一個是可變集合而另一個是不可變集合),則所產生的結果類型與左操作數的類型相同,另外,加號不是集合類型的操作符。
另外,只適合於可變集合的運算符還有:|=, &=, -=, ^=
##怎麼在python中實現switch語句
python中並沒有switch–case語句,但這並不表示我們需要寫大量的elif語句,事實上,我們可以這樣:
代碼示例:
1 | if user.cmd in ('create', 'delete', 'update'): |
1 | msgs = {'create': 'create item', |
使用字典的一大好處是它的搜索操作比類似if-elif-else語句或是for循環這樣的序列查詢速度要快得多。
三元操作符
X if C else Y
代碼示例:
1 | 4, 3 x, y = |
迭代器
迭代器的限制:
迭代器不能向後移動,不能回到開始,不能複制一個迭代器而只能新建另一個。
代碼示例:
1 | 123,'xyz',45.67) myTuple = ( |
注:在迭代可改變對象的時候修改它們並不是個好主意,因為一個序列的迭代器只是記錄你當前到達第幾個元素,所以如果你在迭代的時候改變了元素,更新會立刻反映到你所迭代的條目上。
列表解析
語法:
[expr for iter_var in iterable if cond_expr]
注:列表解析支持多重for循環(為嵌套關係)和多個if語句(為並列關係)
代碼示例:
1 | [x ** 2 for x in range(6)] #這種方式比下面的通過map方法構建的方式效率高 |
迭代矩陣(3×5):
[(x + 1, y + 1) for x in range(3) for y in range(5)]
生成器表達式
語法:(與列表解析語法非常相似)
(expr for iter_var in iterable if cond_expr)
與列表解析不同,生成器表達式並不創建列表,而是返回一個生成器。這個生成器在每次計算出一個條目之後,會把這個條目“生產”出來,這種做法節約了內存。
文件和輸入輸出
輸入輸出方法
注:當使用輸入方法如read()或readlines()時,python並不會刪除行結束符,這個操作被留給了程序員,所以如下的代碼經常會出現:
1 | f = open('myFile','r') |
注:write()和writelines()也不會自動添加行結束符。
truncate()接受一個可選的size作為參數,若指定則文件將被截取到最多size個字節處;若沒有傳遞,則默認截取到文件指針所指向的當前位置。例如:你打開一個文件之後立刻調用該方法,則你打開的這個文件會被刪除。
seek()接受一個叫做offset的參數,該函數可移動文件指針到不同的位置。offset若為0,則表示移動文件指針到文件開頭,為1則表示從當前位置開始算起,為2時則會移動到文件末尾。tell()可告訴你當前文件指針的位置。
sys.argv為命令行參數的列表,其長度len(sys.argv)為參數個數。
注:若要查詢os模塊對文件、目錄的操作方法,可查閱本書9.7節。
檢測和處理異常
異常可以通過try語句來檢測,try語句主要有兩種形式:try-except和try-finally。這兩個語句是互斥的,即你只能使用其中一種。一個try語句可對應多個except語句,但只能對應一個finally語句,或是一個try-except-finally複合語句。你可以使用try-except語句檢測和處理異常,你也可以添加一個可選的else語句處理沒有檢測到異常時執行的代碼,而try-finally只允許檢測異常並做一些必要的清除工作(無論發生錯誤與否),沒有任何異常處理設施。然而複合語句可以做到以上兩者。
try語句塊中異常發生點之後的剩餘語句將永遠不會被執行,一旦一個異常被引發,解釋器將搜索處理器。一旦找到,就開始執行處理器中的代碼,若沒有找到,則向上移交給調用者處理,若始終找不到,python解釋器會顯示出跟踪記錄。
我們還可以在一個except語句中處理多個異常,except語句在處理多個異常時要求異常被放到一個元組中。
1 | except(exc1[, exc2[, ...excn]])[as reason]: |
異常參數
異常可以擁有參數,異常引發之後它會被傳遞給異常處理器,該參數是作為附加信息傳遞給處理器的,代碼示例如下:
1 | except exception as e: #e即為異常參數 |
e為一個包含來自導致異常的代碼的診斷信息的類實例,異常參數自身會組成一個元組,並存儲為類實例(異常類的實例)的屬性。你可以通過print函數來打印e中所包含的信息,你還可以通過str函數來獲得一個比較友好的字符串表示。
異常語句中else的含義
在else範圍中的任何語句被執行之前,try範圍中的所有代碼必須完全執行成功,即運行結束之前沒有引發任何異常。而finally範圍中的代碼則是無論異常是否發生,是否捕捉成功都會被執行。
完成的檢測與處理異常的代碼結構
1 | try: |
注:無異常時執行ACD,有異常時執行ABD。
try-finally
try與finally單獨成對使用時,try內產生一個異常之後,會立即跳轉到finally語句段。finally執行完畢之後,會繼續向上一層引發異常。注:若finally中的代碼引發了另一個異常或由於return,break,continue語法而終止,原來的異常將丟失且無法重新引發。
with語句
注:這一塊的內容不是很懂,這裡只舉簡單一例。
1 | with open('myFile','r') as f: |
異常和sys模塊
另一種獲取異常信息的途徑是通過sys模塊中的exc_info()函數,此功能提供一個三元組的信息,多於我們單純用異常參數所能獲得的信息。
代碼示例:
1 | try: |
我們能從sys.exc_info()得到的元組中是:
- exc_type:異常類;
- exc_value:異常類的實例;
- exc_traceback:跟踪記錄對象
《Python核心編程》筆記(二)