全文共2911字,預計學習時長9分鐘
在編程中,函數就是生命!
作為使用Python的新手——無論是編程新手,還是熟悉另一語言的人——都需要學習函數定義中的參數數目是否和想要傳達的變元數目匹配。
這是基礎性知識——有助於了解這個世界。
然而,接觸到函數定義中的*args和**kwargs時,也會讓新手剛開始就遇到心理障礙。
在Python中的代碼中經常會見到這兩個詞 args 和 kwargs,前面通常還會加上一個或者兩個星號。
別被這些語句所絆倒。其實這些並不是什麼超級特殊的參數,也並不奇特,只是編程人員約定的變量名字,args 是 arguments 的縮寫,表示位置參數;kwargs 是 keyword arguments 的縮寫,表示關鍵字參數。
這其實就是 Python 中可變參數的兩種形式,並且 *args 必須放在 **kwargs 的前面,因為位置參數在關鍵字參數的前面。
接下來,我們就具體學學如何使用它們。
位置參數vs關鍵字參數
為了學習什麼是*args和**kwargs,我們需要區分兩個概念。
首先,分清楚位置參數和關鍵字參數的區別。在最基本的函數中,做一個匹配遊戲——參數1與參數1匹配,參數2與參數2匹配,諸如此類。
def printThese(a,b,c): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored inc")printThese(1,2,3)"""1 is stored in a2 is stored in b3 is stored in c"""
三項參數都是必需的,缺了其中一個就會致錯。
def printThese(a,b,c): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored inc")printThese(1,2)"""TypeError: printThese() missing 1 required positional argument: 'c'"""
為某函數定義中的參數給定默認值,該參數隨後就會變為可選參數。
def printThese(a,b,c=None): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored inc")printThese(1,2)"""1 is stored in a2 is stored in bNone is stored in c"""
另外,這些可選參數也會成為可供選擇的關鍵字,則此時可以規定函數調用參數名稱並相應進行映射。
將三個變量默認值設為None,然後看看如何在不考慮順序的情況下進行映射。
defprintThese(a=None,b=None,c=None): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored inc")printThese(c=3, a=1)"""def printThese(a=None,b=None,c=None): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored inc")printThese(c=3, a=1)"""1 is stored in aNone is stored in b3 is stored in c"""
Splat運算符
從開始說我愛該運算符的名稱開始——太……可視化了。*常常與乘法運算有關,但是在Python中,則是splat運算符的兩倍。
該運算符就像一個彩盒。筆者把延伸運算符——相當於splat的JavaScript——這個過程可以看做是打開一個多米諾骨牌,形成一個更大的序列,但是splat需要更有力的類比。
利用以下例子更容易解釋清楚。
a = [1,2,3]b = [*a,4,5,6]print(b) # [1,2,3,4,5,6]
在代碼實例中,將a的內容移入(解包)到新列表b中。
如何使用*args和**kwargs
我們知道splat運算符解包多個值,並且知道函數參數有兩種類型。若現在還未弄明白,那麼可以將*args理解為變元的縮寫,而**kwargs理解為關鍵字變元的縮寫。
各參數用於解壓其各自的變元類型,允許使用可變字長變元列表進行函數調用。例如,創建一個函數表示學生的考試分數。
def printScores(student,*scores): print(f"Student Name:{student}") for score in scores: print(score)printScores("Jonathan",100, 95, 88, 92, 99)"""Student Name: Jonathan10095889299"""
噢,等等,我並未稱呼其為*args?是的,「args」是一個標準化規範,但仍然只是一個名稱。事實上,在*args中,唯一的星號是真正的參與者,創建了列表,其內容則是來自函數調用的位置參數(在這些定義變元後)。
這些理清楚之後,**kwargs就很容易理解了。名稱並不重要,重要的是雙星號創建了字典,其內容是關鍵字參數,來自函數調用(在這些定義變元後)。
為了更好地演示,我們創建一個函數,輸出參加全國英語等級考試的人員名單。
def printPetNames(owner,**pets): print(f"Owner Name:{owner}") for pet,name in pets.items(): print(f"{pet}:{name}")printPetNames("Jonathan", dog="Brock",fish=["Larry", "Curly", "Moe"],turtle="Shelldon")"""Owner Name: Jonathandog: Brockfish: ['Larry', 'Curly', 'Moe']turtle: Shelldon"""
最後,再給大家提供一些額外的「知識福利」。
下面一些諫言可有助於大家規避常見的陷阱並擴展知識面。
· 利用*args和**kwargs作為標準化規範,把握好位置參數和關鍵字參數;
· 不能將**kwargs置於*args前,否則將產生錯誤;
· 清楚意識到關鍵字參數和**kwargs之間的衝突,該值本是傳達**kwarg的意思,但是卻不明就裡的成為關鍵字參數的名稱;
· 在函數調用時可以採用splat運算符。
留言點讚關注
我們一起分享AI學習與發展的乾貨
如轉載,請後臺留言,遵守轉載規範