前面文章中,在定義爬蟲函數時重點研究了*args、**kwargs兩個參數的使用方法。
https://www.cnblogs.com/chen117/p/12952601.html
但在后面的學習中發現,當時對函數的理解還比較粗淺,經過更深入的學習——主要還是看了下面這篇知乎的狠貼,顛覆了之前了解的分類方式,所以專門寫這篇總結一下。
https://www.zhihu.com/question/57726430
(當前最新的python版本是 3.8.3)
函數參數的作用是傳遞數據給函數使用。
一、參數有兩種形式:形參、實參。
【實參】
調用函數時的參數,格式:
https://www.cnblogs.com/chen117/p/12952601.html
| funcname(實參表) |
實參表由左到右就是簡單的兩個部分:
| funcname(位置實參, 關鍵字實參) |
注意:這兩種實參前后順序是嚴格的,兩個部分都可以缺省,但不能相互交錯。(這確定了位置匹配的唯一性)
“關鍵字實參”可以擺脫位置約束。兩種實際參數要共同覆蓋所有沒有默認值的形式參數。
例1:(關鍵字實參形式可以擺脫位置約束)


【形參】
定義函數時的參數。
# 函數定義,獨立成塊的代碼,圓括號內是形式參數
| def funcname(形參表): 函數體 |
形參從左到右可以分為五個部分:
| def funcname(【限定位置形參】,【普通形參】,【特殊形參args】,【限定關鍵字形參】,【特殊形參kwargs】): pass |
其中兩個特殊形參分別只能是0個或1個,其他形參可以是0個或多個。
盡管函數定義的形式如此豐富,但調用形式永遠是簡單的兩部分——位置實參+關鍵字實參,與有無默認值無關。
二、形參類型:
1、限定位置形參:
純位置形參。是為了限制開頭幾個參數只能按位置傳遞。(不能使用關鍵字實參形式)
Python從3.7開始,為某些內置函數定義了positional-only的形參。從Python 3.8開始,positional-only形參將可正式用於自定義函數中,它們必須放在形參表的最前面,並在后面使用斜杠/(獨占一個參數位)與普通形參分隔。
例2.1:(a,b,c為限定位置形參,不能按關鍵字傳遞)


2、普通形參:
按最簡形式定義出來的就是【普通形參】,它們是“位置、關鍵字兼容”的。
例2.2:( d為普通形參,可以按位置傳遞,也可以按關鍵字傳遞)
3、限定關鍵字形參(命名關鍵字參數)
(keyword-only)限制后面幾個參數只能按關鍵字傳遞,這往往是因為后面幾個形參名具有十分明顯的含義,顯式寫出有利於可讀性;或者后面幾個形參隨着版本更迭很可能發生變化,強制關鍵字形式有利於保證跨版本兼容性。
必須傳入參數名,可以有缺省值。
例3.1:(d為限定關鍵字參數,只能按關鍵字傳遞)



例3.2:(當限定關鍵字參數d有缺省值時,可以省略)


4、特殊形參:*args
是一種可變參數,也叫元組參數。可以是元組也可以是列表序列。這種形式表示接受任意多個實際參數將其放到一個元組tuple中。
它位於普通形參之后,又只能接受位置實參。
例4:(雖然叫元組參數,但不要傳入一個元組對象進去,需要 * 解封。)


5、特殊形參:**kwargs
也是一種可變參數,也叫關鍵字參數、字典參數,這種形式表示接受任意多個實際參數將其放到一個字典dict中。
關鍵字參數是一個由鍵值對組成的集合,允許通過變量名進行匹配,而不是位置。
例5:(雖然叫字典參數,但不能傳入一個完整的字典對象,需要**解封)


6、混合參數
*args接收多余的位置實參,**kwargs接收多余的關鍵字實參。
*args 和 **kwargs 並不是 python 中的參數關鍵字,而是一種慣用寫法。
例6.1:


例6.2:命名關鍵字參數不能與可變參數 *args 組合,可以與 **kwargs 組合。


四、特殊傳參方法:
1、序列解包:
當你有個序列對象,想將其中元素解放出來作為調用函數的位置實參時,給它加個前綴*即可。
例7:


2、字典解包:
當你有個字典對象,且其中的鍵都是合法的形參名時,想把其中的鍵值對解放出來作為調用函數的關鍵字參數,給它加個前綴**即可。
例8:


五、參數傳遞基本法則:
將實際參數傳遞給形參的方式有兩種:
值傳遞:實參為不可變對象,傳遞給形參后,形參的值改變,實參值不變。
引用傳遞:實參為可變對象,傳遞給形參后,形參的值改變,實參值改變。(傳遞地址)
當函數被調用時,解釋器會查看傳入的變量(內存地址)指向的類型,如果是可變類型的值,就按照引用傳遞變量;如果是一個非可變類型的值,就按照值傳遞變量。
盡管函數定義的形式如此豐富,但調用形式永遠是簡單的兩部分——位置實參+關鍵字實參。注意這兩個前后順序是嚴格的,兩個部分都可以缺省。
與有無默認值無關,位置實參永遠按位置傳遞給*或*args之前對應的形參(即限定位置形參和普通形參),多余的位置實參傳入*args(如果有的話);
關鍵字實參則匹配剩下的普通形參和限定關鍵字形參(非限定位置形參),多余的關鍵字實參則傳入**kwargs(如果存在的話)。
