天天看點

第十二次課:Python函數(三)

清單生成式

  清單生成式是Python函數的進階特性,顧名思義就是用來建立清單(list)的生成式。

  基礎文法: [exp for iter_var in iterable] 

  如[x * x for x in range(1, 11)] 就是一個清單生成式。首先疊代 iterable 裡所有内容, 每一次疊代, 都把 iterable 裡相應内容放到 iter_var 中, 再在表達式 exp 中應用該 iter_var 的内容, 最後用表達式的計算值生成一個新的清單。

  從例子中可以很直覺的看出無論是用循壞還是普通函數,代碼都有好幾行,而使用清單生成式就一行代碼實作了功能,及簡化了代碼又有更好的複用性。

  生成式for循環後還是使用if判斷語句,如下例子:

  生成式可以使用兩層循環,如下例子:格式化輸出某位學生所有科目的考試成績

  清單生成式雖然簡潔易用,但有的情形不用:當需要隻是執行一個循環的時候;當有内建的操作或者類型能夠以更直接的方式實作的;如果需要對每個元素都調用并且傳回結果時。

生成器

  當我們調用一個普通的python函數時,一般都是從函數的第一行開始執行,直到遇到return語句或者異常或者函數的最後一行。這樣,函數就将控制權交還與調用者,函數中的所有工具以及局部變量等資料都将丢失。再次調用這個函數的時候,所有的局部變量,堆棧資訊都将重新建立,跟之前的調用再無關系。

  生成器(generator)其實對我們來說并不陌生,最簡單的方法就是把清單的方括号改成圓括号,如下:

  有時候我們并不希望函數隻傳回一個值,而是希望傳回一個序列。要做到這一點,這種函數需要能夠儲存自己的工作狀态。這樣的話,就不能使用我們通常所使用的return語句,因為一旦使用return語句,代碼執行的控制權就交給了函數被調用的地方,函數的所有狀态将被清零。在這種情況下,我們就需要使用yield關鍵字。含有yield關鍵字的地方,就是一個生成器(generator)。

  在python中,生成器通過生成器函數生成,生成器函數定義的方法跟普通函數定義的方法一緻。唯一不同的地方是,生成器函數不用return傳回,而是用yield關鍵字一次傳回一個結果,在每個結果之間挂起與繼續他們的狀态,來自動實作疊代(循環)。 

(1)當調用生成器函數時候,函數傳回的,隻是一個生成器對象,并沒有真正執行裡面的邏輯; 

(2)當next()方法第一次被調用以後,生成器才真正開始工作。一旦遇到yield語句,代碼便停止運作。注意此時的停止運作跟return的是不一樣的;

(3)調用next()方法的時候,傳回的是yield處的參數值;

(4)當繼續調用next()方法時,代碼将在上一次停止的yield語句處繼續執行,并且到下一個yield處停止; 

(5)一直到後面沒有yield語句,最後抛出StopIteration的異常;

疊代器

  在Python中,如果給定一個清單(list)或元組(tuple),我們可以通過for循環來周遊這個清單(list)或元組(tuple),這種周遊我們成為疊代(Iteration)。在Python中,疊代是通過 for ... in 來完成的。隻要是實作了__iter__()方法的對象,就可以使用疊代器進行通路。

  疊代操作就是對于一個集合,無論該集合是有序還是無序,我們用 for 循環總是可以依次取出集合的每一個元素。這類集合稱作可疊代對象,字典就是典型的可疊代對象,下面舉例:

裝飾器

  裝飾器(Decorator)其實就是一個以函數作為參數并傳回一個替換函數的可執行函數。

  首先,定義了一個帶單個參數func1的名為outer的函數。然後在outer内部定義了一個内嵌函數inner。inner函數将列印一行字元串然後調用func1,并在#1處擷取其傳回值。在每次outer被調用時,func1的值可能都會不同,但不論func1是什麼函數,都将調用它。最後,inner傳回func1()的傳回值加1。在#2 處可以看到,當調用指派給decorated的傳回函數時,得到的是一行文本輸出和傳回值2,而非期望的調用foo的傳回值1。

練習:利用函數實作九九乘法表:

繼續閱讀