在C#中沒有獨(dú)立的函數(shù)存在,只有類的(動(dòng)態(tài)或靜態(tài))方法這一概念,它指的是類中用于執(zhí)行計(jì)算或其它行為的成員。在Python中,你可以使用類似C#的方式定義類的動(dòng)態(tài)或靜態(tài)成員方法,因?yàn)樗cC#一樣支持完全的面向?qū)ο缶幊?。你也可以用過程式編程的方式來編寫Python程序,這時(shí)Python中的函數(shù)與類可以沒有任何關(guān)系,類似C語言定義和使用函數(shù)的方式。此外,Python還支持函數(shù)式編程,雖然它對(duì)函數(shù)式編程的支持不如LISP等語言那樣完備,但適當(dāng)使用還是可以提高我們工作的效率。 本章主要介紹在過程編程模式下Python中函數(shù)的定義和使用方法,關(guān)于在面向?qū)ο缶幊讨腥绾问褂煤瘮?shù),我們將在下一章再討論。此外,我還會(huì)簡(jiǎn)要介紹Python中的函數(shù)編程功能。 3.1 函數(shù)的定義函數(shù)定義是最基本的行為抽象代碼,也是軟件復(fù)用最初級(jí)的方式。Python中函數(shù)的定義語句由def關(guān)鍵字、函數(shù)名、括號(hào)、參數(shù)(可選)及冒號(hào):組成。下面是幾個(gè)簡(jiǎn)單的函數(shù)定義語句:
可能你已經(jīng)注意到了,Python定義函數(shù)的時(shí)候并沒有約束參數(shù)的類型,它以最簡(jiǎn)單的形式支持了泛型編程。你可以輸入任意類型的數(shù)據(jù)作為參數(shù),只要這些類型支持函數(shù)內(nèi)部的操作(當(dāng)然必要時(shí)需要在函數(shù)內(nèi)部做一些類型判斷、異常處理之類的工作)。 3.2 函數(shù)的參數(shù)3.2.1 C#與Python在函數(shù)參數(shù)定義方面的差別C#中方法的參數(shù)有四種類型: (1) 值參數(shù)不含任何修飾符 Python中函數(shù)參數(shù)的形式也有四種類型: (1) f(arg1,arg2,...) 這是最常用的函數(shù)定義方式 可以看出,Python函數(shù)參數(shù)定義與C#相比,最大的兩個(gè)區(qū)別是支持關(guān)鍵字參數(shù)和字典參數(shù)。
3.29更新:根據(jù)JeffreyZhao提示,C# 4.0 已經(jīng)支持命名參數(shù)(即關(guān)鍵字參數(shù))和可選參數(shù)(即參數(shù)默認(rèn)值),詳情可見生魚片blog上的:《C#4.0新特性:可選參數(shù),命名參數(shù),Dynamic》。在此向兩位致謝。
3.2.2 關(guān)鍵字參數(shù)關(guān)鍵字參數(shù)可以使我們調(diào)用含有很多參數(shù)、同時(shí)一些參數(shù)具有默認(rèn)值的Python函數(shù)變得更簡(jiǎn)單,也是Python實(shí)現(xiàn)函數(shù)重載的一種重要手段(到類與對(duì)象部分再詳細(xì)說這個(gè)問題)。下面的例子說明了如何定義和調(diào)用含關(guān)鍵字參數(shù)的函數(shù)(引自Guido van Rossum《Python入門》,包括后面的幾個(gè)例子):
3.2.3 字典參數(shù)如果形參表中有一個(gè)形為**name的形參,在調(diào)用時(shí)這個(gè)形參可以接收一個(gè)字典,字典中包含所有不與任何形參匹配的關(guān)鍵字參數(shù)。例如下面的函數(shù):
client : John Cleese 3.2.4 函數(shù)參數(shù)調(diào)用的順序調(diào)用Python函數(shù)時(shí),參數(shù)書寫的順序分別為:非關(guān)鍵字參數(shù),關(guān)鍵字參數(shù),元組參數(shù),字典參數(shù)。請(qǐng)記住以下幾點(diǎn)規(guī)則: * 通過位置分配非關(guān)鍵字參數(shù) 一般說來,實(shí)參表中非關(guān)鍵字參數(shù)在前,關(guān)鍵字參數(shù)在后,關(guān)鍵字名字必須是形參名字。形參有沒有缺省值都可以用關(guān)鍵字參數(shù)的形式調(diào)用。每一形參至多只能對(duì)應(yīng)一個(gè)實(shí)參,因此,已經(jīng)由位置參數(shù)傳入值的形參就不能在同一調(diào)用中再作為關(guān)鍵字參數(shù)。 總之,由于Python的函數(shù)參數(shù)定義和調(diào)用方式太靈活了,所以一開始容易把人搞暈。不過可以慢慢來,你會(huì)越來越發(fā)現(xiàn)Python的簡(jiǎn)便所在。 3.3 函數(shù)文檔在C#,可以使用文檔XML標(biāo)記對(duì)函數(shù)進(jìn)行注釋,這樣在VS等IDE中,輸入函數(shù)名后就會(huì)提示函數(shù)的功能、參數(shù)及返回值等的說明,方便函數(shù)的調(diào)用者。在Python中,也有類似的功能,即文檔字符串(Docstrings)。但Python的文檔字符串不像C#中的文檔XML標(biāo)記那么豐富,基本等同于C#中的<summary>標(biāo)記,下面讓我們一起來通過一個(gè)例子了解一下(引自《簡(jiǎn)明Python教程》):
輸出 $ python func_doc.py The two values must be integers. 在上述函數(shù)中,第一個(gè)邏輯行的字符串是這個(gè)函數(shù)的文檔字符串。文檔字符串的慣例是一個(gè)多行字符串,它的首行以大寫字母開始,句號(hào)結(jié)尾。第二行是空行,從第三行開始是詳細(xì)的描述,描述對(duì)象的調(diào)用方法、參數(shù)說明、返回值等具體信息。 可以使用__doc__(注意雙下劃線)調(diào)用printMax函數(shù)的文檔字符串屬性(屬于函數(shù)的名稱,請(qǐng)記住Python把每一樣?xùn)|西都作為對(duì)象,包括這個(gè)函數(shù))。它等同于用Python的內(nèi)建函數(shù)help()讀取函數(shù)的說明。很多Python的IDE也依賴于函數(shù)的文檔字符串進(jìn)行代碼的智能提示,因此我們?cè)诰帉懞瘮?shù)時(shí)應(yīng)養(yǎng)成編寫文檔字符串的習(xí)慣。 3.4 函數(shù)編程Python中加入了一些在函數(shù)編程語言和Lisp中常見的功能,如匿名函數(shù)、高階函數(shù)及列表內(nèi)涵等,關(guān)于最后一個(gè)問題我在《2 運(yùn)算符、表達(dá)式和流程控制》已經(jīng)介紹過了,本章只介紹匿名函數(shù)和高階函數(shù)。 3.4.1 匿名函數(shù)lambda函數(shù)是匿名函數(shù),用來定義沒有名字的函數(shù)對(duì)象。在Python 中,lambda只能包含表達(dá)式:lambda arg1, arg2 ... : expression。lambda 關(guān)鍵字后就是逗號(hào)分隔的形參列表,冒號(hào)后面是一個(gè)表達(dá)式,表達(dá)式求值的結(jié)果為lambda的返回值。 雖然lambda的濫用會(huì)嚴(yán)重影響代碼可讀性,不過在適當(dāng)?shù)臅r(shí)候使用一下lambda 來減少鍵盤的敲擊還是有其實(shí)際意義的,比如做排序的時(shí)候,使用data.sort(key=lambda o:o.year)顯然比
要方便許多。(引自《可愛的Python》)
3.29更新:根據(jù)JeffreyZhao提示,重新整理C#中匿名函數(shù)的內(nèi)容(本部分主要參考MSDN,見http://msdn.microsoft.com/zh-cn/library/bb882516.aspx): 在C#中也有匿名函數(shù)功能。在 C# 1.0 中,通過使用在代碼中其他位置定義的方法顯式初始化委托來創(chuàng)建委托的實(shí)例。C# 2.0引入了匿名方法的概念,作為一種編寫可在委托調(diào)用中執(zhí)行的未命名內(nèi)聯(lián)語句塊的方式。C# 3.0 引入了 Lambda表達(dá)式,這種表達(dá)式與匿名方法的概念類似,但更具表現(xiàn)力并且更簡(jiǎn)練。這兩個(gè)功能統(tǒng)稱為“匿名函數(shù)”。通常,針對(duì) .NET 3.5 及更高版本的應(yīng)用程序應(yīng)使用 Lambda 表達(dá)式。 Lambda 表達(dá)式可以包含表達(dá)式和語句,并且可用于創(chuàng)建委托或表達(dá)式目錄樹類型。所有 Lambda 表達(dá)式都使用 Lambda 運(yùn)算符 =>, 運(yùn)算符的左邊是輸入?yún)?shù)(如果有),右邊包含表達(dá)式或語句塊??梢詫⒋吮磉_(dá)式分配給委托類型,如下所示:
3.4.2 高階函數(shù)高階函數(shù)(High Order)是函數(shù)式編程的基礎(chǔ),常用的高階函數(shù)有: Python通過map、filter、reduce三個(gè)內(nèi)置函數(shù)來實(shí)現(xiàn)上述三類高階函數(shù)功能。本文不對(duì)這三個(gè)函數(shù)的用法進(jìn)行詳細(xì)介紹,僅給出它們使用的示例代碼(引自《Python的map、filter、reduce函數(shù)》),請(qǐng)細(xì)細(xì)體會(huì):
運(yùn)行結(jié)果如下: |
|