函數(shù)定義:
代碼復用的第一步是使用函數(shù),它是命名的用于區(qū)分的代碼段。函數(shù)可以接受任何數(shù)字或其他類型的輸入作為參數(shù),并且返回數(shù)字或其他類型的結(jié)果。
定義函數(shù)的格式: def functionname (參數(shù)一,參數(shù)二,。。。):
傳入函數(shù)的值稱為參數(shù),函數(shù)的參數(shù)可以沒有,當函數(shù)調(diào)用的時候,這些參數(shù)的值會被賦值給函數(shù)中的對應(yīng)參數(shù)。
通過直接輸入函數(shù)名來調(diào)用函數(shù)。

這個函數(shù)做了以下事情:
把'blue'賦值給函數(shù)的內(nèi)部參數(shù)color
運行if-elif-else的邏輯鏈
返回一個字符串
將該字符串賦值給變量comment
注意:如果函數(shù)不顯式調(diào)用return函數(shù),那么默認返回None。

注意:None是Python中一個特殊的值,不表示任何數(shù)據(jù),作為布爾值的時候喝False是一樣的,但是和False還是又一定差別。

我們要把None和不含任何值的空數(shù)據(jù)結(jié)構(gòu)區(qū)分開來。0值的整型/浮點型,空字符串(' '),空列表([ ] ),空元組(( , )),空字典({ }),空集合(set())都等價于False,但是不等于None。
位置參數(shù):
Python處理參數(shù)的方式要比其他的語言更加靈活。傳入?yún)?shù)的值是按照順序依次復制過去的。
栗子:創(chuàng)建一個帶有位置參數(shù)的函數(shù),并且返回一個字典:

弊端:需要記住每個位置參數(shù)的意義。
關(guān)鍵字參數(shù):
為了避免位置參數(shù)帶來的混亂,調(diào)用參數(shù)時可以指定對應(yīng)參數(shù)的名字,甚至可以才用與函數(shù)定義不同的順序調(diào)用:

我們還可以把位置參數(shù)和關(guān)鍵字參數(shù)混合起來,首先實例化參數(shù)wine,然后對參數(shù)entree和dessert使用關(guān)鍵字參數(shù)的方式:

如果同時出現(xiàn)兩種參數(shù)形式,首先應(yīng)該考慮的時位置參數(shù)。
指定默認參數(shù)值:
當調(diào)用方法沒有提供對應(yīng)的參數(shù)值時,我們可以指定默認參數(shù)值。

注意:默認參數(shù)值在函數(shù)被定義時已經(jīng)計算出來,而不是在程序運行時。還有就是,可變的數(shù)據(jù)類型(例如列表或者字典)不能當作默認參數(shù)值。

使用*收集位置參數(shù):
Python是沒有指針概念的。
當參數(shù)被用在函數(shù)內(nèi)部的時候,星號將一組可變數(shù)量的位置參數(shù)集合成參數(shù)值的元組。在下面的栗子中args是傳入到函數(shù)print_args()的參數(shù)值的元組:

對于編寫參數(shù)可變的函數(shù)使用 * 收集參數(shù)是很方便的,如果函數(shù)有限定的位置參數(shù),那么*args會收集剩下的參數(shù):

使用**收集關(guān)鍵字參數(shù):
使用兩個星號可以將參數(shù)收集到一個字典中,參數(shù)的名字是字典的鍵,對應(yīng)參數(shù)的值是字典的值??磦€小栗子:

在函數(shù)內(nèi)部,kwargs是一個字典。
如果把帶有*args和**kwargs的位置參數(shù)混合起來,它們會按照順序解析。調(diào)用時不需要參數(shù)kwargs。
文檔字符串:
為了提高程序的可讀性,建議在函數(shù)體開始的部分附上函數(shù)定義說明的文檔,這就是函數(shù)的文檔字符串。
調(diào)用Python的help()函數(shù),可以打印輸出一個函數(shù)的文檔字符串,可以把函數(shù)名傳入函數(shù)help()就會得到參數(shù)列表和規(guī)范的文檔。如果僅僅想得到文檔字符串,可以使用print(echo.__doc__)。其中的:__doc__是作為函數(shù)中變量的文檔字符串的名字。

Python的一等公民:函數(shù)
Python中一切皆對象,包括數(shù)字,字符串,元組,列表,字典和函數(shù)。函數(shù)是python中的一等公民,可以把它們(返回值)賦值給變量,可以作為參數(shù)被其他函數(shù)調(diào)用,也可以從其他函數(shù)中返回值。
當一個函數(shù)作為參數(shù)傳入到另一個函數(shù)的時候,是不需要加括號的,在python中圓括號意味著調(diào)用函數(shù)。
同樣可以把函數(shù)作為列表,元組,集合和字典的元素。函數(shù)名是不可變的,因此可以把函數(shù)用作字典的鍵。
內(nèi)部函數(shù):
在python中可以在函數(shù)中定義另一個函數(shù):

當需要在函數(shù)內(nèi)部多次執(zhí)行復雜的任務(wù)的時候,內(nèi)部函數(shù)是非常有用的,從而避免了循環(huán)和代碼的堆疊重復。下面的小栗子,內(nèi)部函數(shù)的作用是給外部函數(shù)增加字符串參數(shù):

閉包:
內(nèi)部函數(shù)可以看作一個閉包。閉包是一個可以由另一個函數(shù)動態(tài)生成的函數(shù),并且可以改變和存儲函數(shù)外創(chuàng)建的變量的值。
看一個新的栗子:

在上面的栗子中inner2()直接使用外部的saying參數(shù),而不是通過另外一個參數(shù)獲取
knights2()返回值為inner2函數(shù),而不是調(diào)用它
總結(jié)以下就是:inner2()函數(shù)可以得到saying參數(shù)的值并記錄下來。return inner2這一行返回的時inner2函數(shù)的復制(沒有直接調(diào)用)。所以它就是一個閉包:一個被動態(tài)創(chuàng)建的可以記錄外部變量的函數(shù)。
匿名函數(shù):lambda()函數(shù)
python中,lambda函數(shù)是用一個語句表達的匿名函數(shù)。
小栗子:將一個列表中的字符串首字母變成大寫

生成器:
生成器是用來創(chuàng)建Python序列的一個對象。使用它可以迭代龐大的序列,且不需要在內(nèi)存中創(chuàng)建和存儲整個序列。通常,生成器是為迭代器產(chǎn)生數(shù)據(jù)的。生成器栗子:range()函數(shù)。每次迭代生成器函數(shù)時,它會記錄上一次調(diào)用的位置,并且返回下一個值。普通函數(shù)一般不記錄前一次調(diào)用的,一般都會在函數(shù)的第一行開始執(zhí)行。
生成器函數(shù)和普通函數(shù)類似,但是它的返回值使用yield語句聲明而不是return。編寫自己的range()版本:

裝飾器:
有時候我們需要在不修改源代碼的情況下修改已經(jīng)存在的函數(shù)。常見的例子是增加一句調(diào)試聲明,以查看傳入的參數(shù)。
裝飾器實質(zhì)上是一個函數(shù)。它把一個函數(shù)作為輸入并且返回另一個函數(shù)。在裝飾器中,通常使用下面的技巧:
1,*args和**kwargs
2,閉包
3,作為參數(shù)的函數(shù)

無論傳入document_it()的函數(shù)func是什么,裝飾器都會返回一個新的函數(shù),其中包含函數(shù)document_it()增加的額外語句。實際上,裝飾器并不需要執(zhí)行函數(shù)func中的代碼,知識在結(jié)束前函數(shù)document_it()調(diào)用函數(shù)func以便得到func的返回結(jié)果和附加代碼的結(jié)果。
如何使用裝飾器:

一個函數(shù)可以有很多個裝飾器??拷瘮?shù)定義(def上面)的裝飾器最先執(zhí)行,然后依次執(zhí)行上面的裝飾器。任何順序都會得到相同的最終結(jié)果。只是過程稍有不同。
命名空間和作用域:
一個名稱在不同的使用情況可能是不同的事物,python程序有各種各樣的命名空間,它指的是在該程序段內(nèi)一個特定的名稱是獨一無二的,它和其他同名的命名空間是無關(guān)的。
每一個函數(shù)定義自己的命名空間。如果在主程序(main)中定義一個變量 x,在另外一個 函數(shù)中也定義 x 變量,兩者指代的是不同的變量。但是,天下也沒有完全絕對的事情,需 要的話,可以通過多種方式獲取其他命名空間的名稱。
每個程序的主要部分定義了全局命名空間。因此,在這個命名空間的變量是全局變量。我們可以在一個函數(shù)體內(nèi)部得到全局變量:

如果想在函數(shù)中得到一個全局變量的值并且改變它,就會報錯
為了讀取全局變量而不是函數(shù)中的局部變量,需要在變量前面顯式地加關(guān)鍵字global

如果在函數(shù)中不聲明關(guān)鍵字global,python會使用局部命名空間,同時變量也是局部的。函數(shù)執(zhí)行后回到原來的命名空間。
Python中提供了兩種獲取命名空間內(nèi)容的函數(shù):
locals()返回一個局部命名空間內(nèi)容的字典
globals()返回一個全局命名空間內(nèi)容的字典
下面是一個小栗子:

函數(shù)chang_local()的局部命名空間只含有局部變量animal。全局命名空間含有全局變量animal以及其他一些東西。
名稱中 _ 和 __的用法
以兩個下劃線__開頭和結(jié)束的名稱都是python的保留用法。因此,在自定義的變量中不能使用它們。選擇這種命名模式是考慮到開發(fā)者一般是不會選擇它們作為自己的變量的。
例如,一個函數(shù)的名稱是系統(tǒng)變量function.__name__,它的文檔字符串是function.__doc__:

如同之前 globals 的輸出結(jié)果所示,主程序被賦值特殊的名字 __main__。
使用try和except處理錯誤:
注意:在不能提供異常捕獲代碼時,Python會輸出錯誤消息和關(guān)于錯誤發(fā)生處的信息,然后終止程序。
關(guān)于錯誤和異常處理,我之前寫的一個文章:
http://blog.csdn.net/lufeisan/article/details/53158301
注:本文內(nèi)容來自《Python語言及其應(yīng)用》歡迎購買原書閱讀