官术网_书友最值得收藏!

6.2 靈活即強大

視頻講解

有時候,評論一種編程語言是否優秀,往往是看它是否靈活。靈活并非意味著無所不能、無所不包,那樣就會顯得龐大和冗雜。靈活應該表現為多變,如前面學到的參數,函數因參數而靈活。如果沒有參數,一個函數就只能死板地完成一個功能、一項任務。

6.2.1 形參和實參

參數從調用的角度來說,分為形式參數(parameter)和實際參數(argument)(注:本書后面簡稱為“形參”和“實參”)。與絕大多數編程語言一樣,形參指的是函數定義的過程中小括號里的參數,而實參則指的是函數在被調用的過程中傳遞進來的參數。

舉個例子:

sayHi(name)中的name是一個形參,因為它只是代表一個位置、一個變量名;而調用sayHi("小甲魚")傳遞的"小甲魚"則是一個實參,因為它是一個具體的內容,是賦值到變量name中的值。

6.2.2 函數文檔

給函數寫文檔是為了讓后人可以更好地理解你的函數設計邏輯,對于一名優秀的程序員來說,養成編寫函數文檔的習慣無疑是非常必要的。因為在實際開發中,個人的工作量和能力確實相當有限,因此中、大型的程序永遠都是團隊來完成的。大家的代碼要相互銜接,就需要先閱讀別人提供的文檔,因此適當的文檔說明非常重要。而函數文檔的作用是描述該函數的功能以及一些注意事項:

例如該匯率轉換函數,因為匯率其實每天都在變化,所以如果沒有注明指定匯率的日期,就可能會導致數據產生偏差。

可以看到,函數開頭的幾行字符串并不會被打印出來,但它將作為函數的一部分存儲起來。這個字符串稱為函數文檔,它的功能與代碼注釋是一樣的。

有讀者可能會說,既然一樣,搞那么復雜干啥呀?其實也不是完全一樣,函數的文檔字符串可以通過特殊屬性_ _doc_ _獲取(注:_ _doc_ _兩邊分別是兩條下畫線):

另外,當想使用一個BIF卻又不確定其用法的時候,可以通過help()函數來查看函數的文檔:

6.2.3 關鍵字參數

前面在定義函數的時候,就已經把參數的名字和位置確定下來,Python中這類位置固定的參數稱為位置參數。對于函數的調用者來說,只需要知道按照順序傳遞正確的參數就可以了。

可是有些啥時候,粗心的程序員很容易會搞亂位置參數的順序,以至于函數無法按照預期實現。對于這類情況,使用關鍵字參數就很有用了。

舉個例子:

關鍵字參數其實就是在傳入實參時明確指定形參的變量名,其特點就是參數之間不存在先后順序。盡管使用這種技巧要多輸入一些字符,但隨著程序規模越大、參數越多的時候,關鍵字參數起到的作用就越明顯。畢竟寧可多輸入幾個字符,也不希望出現料想不及的BUG。

另外,在調用函數的時候,位置參數必須在關鍵字參數的前面,否則就會出錯:

     >>> eat(something="蛋糕", "小甲魚")
     SyntaxError: positional argument follows keyword argument

6.2.4 默認參數

Python的函數允許為參數指定默認的值,那么在函數調用的時候如果沒有傳遞實參,則采用默認參數值:

可以看到,默認參數使得函數的調用更加便捷了。這就像日常安裝應用程序,可以選擇自定義或者默認安裝,我想絕大多數普通用戶都會選擇默認安裝的,對吧?

結合默認參數和關鍵字參數,可以使函數的調用變得非常靈活:

另外,在定義函數的時候,位置參數必須在默認參數的前面,否則就會出錯:

     >>> def watchMovie(name="小甲魚", cigarette=True, beer=True, girlfriend):
         pass
     SyntaxError: non-default argument follows default argument

6.2.5 收集參數

這個名字看起來比較新鮮,其實大多數時候它也被稱為可變參數。有時候,可能函數也不知道調用者實際上會傳入多少個實參,這看起來很可笑,對嗎?其實不然,例如我們熟悉的print()函數就是這樣:

     >>> print(1, 2, 3, 4, 5)
     1 2 3 4 5
     >>> print("I", "Love", "FishC")
     I Love FishC

若實參個數不確定,在定義函數的時候,形參就可以使用收集參數來“搞定”。而語法也很簡單,僅需要在參數前面加上星號(*)即可:

其實大家仔細思考后也不難理解,Python就是把標志為收集參數的參數們打包成一個元組。

不過這里需要注意一下,如果在收集參數后面還需要指定其他參數,那么在調用函數的時候就應該使用關鍵參數來指定,否則Python就都會把實參都納入到收集參數中。

舉個例子:

建議大家如果定義的函數中帶有收集參數,那么可以將其他參數設置為默認參數,例如,print()的原型如下:

     print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

objects參數是一個收集參數,如果傳入多個參數,將依次打印出來;sep參數指定多個參數之間的分隔符,默認是空格;end參數指定以什么字符結束打印,默認是換行符;file參數指定輸出的位置;flush指定是否強制刷新緩存。

在函數的定義中,收集參數前面的星號(*)起到的作用稱為“打包”操作,通俗的理解就是將多個參數打包成一個元組的形式進行存儲。

在這里給大家介紹一個有趣的技能:星號(*)在形參中的作用是“打包”,而在實參中的作用則相反,起到“解包”的作用。

舉個例子:

     >>> num = (1, 2, 3, 4, 5)
     >>> print(num)
     (1, 2, 3, 4, 5)
     >>> print(*num)
     1 2 3 ?4 5

“解包”操作也適用于其他的序列類型:

     >>> name = "FishC"
     >>> print(*name)
     F i s h C
     >>> list1 = [1, 1, 2, 3, 5]
     >>> print(*list1)
     1 1 2 3 5

Python還有另一種收集方式,就是用兩個星號(**)表示。與前面的介紹不同,兩個星號的收集參數表示為將參數們打包成字典的形式。字典的概念還沒有接觸,所以在后面講解字典的章節中再給大家介紹吧。

主站蜘蛛池模板: 辉县市| 永济市| 深州市| 灵石县| 鸡泽县| 泽库县| 江永县| 乃东县| 平顺县| 罗江县| 达尔| 太康县| 彝良县| 且末县| 海城市| 寿光市| 沂水县| 揭东县| 重庆市| 英吉沙县| 陇川县| 宝兴县| 雅江县| 苍山县| 建湖县| 哈尔滨市| 安溪县| 化德县| 九台市| 铜川市| 崇仁县| 阿图什市| 绵阳市| 江源县| 衡阳市| 公主岭市| 廉江市| 嵊泗县| 邛崃市| 宝山区| 钟山县|