摘要:在調用函數時,我們可以給該函數傳遞任意個參數,包括個參數傳遞個參數傳遞個參數傳遞個參數傳遞個參數上面的表示任意參數,實際上,它還有另外一個用法用來給函數傳遞參數。應該使用不可變對象作為函數的默認參數。
函數參數
在 Python 中,定義函數和調用函數都很簡單,但如何定義函數參數和傳遞函數參數,則涉及到一些套路了。總的來說,Python 的函數參數主要分為以下幾種:
必選參數
默認參數
可變參數
關鍵字參數
必選參數必選參數可以說是最常見的了,顧名思義,必選參數就是在調用函數的時候要傳入數量一致的參數,比如:
>>> def add(x, y): # x, y 是必選參數 ... print x + y ... >>> add() # 啥都沒傳,不行 Traceback (most recent call last): File "默認參數", line 1, in TypeError: add() takes exactly 2 arguments (0 given) >>> add(1) # 只傳了一個,也不行 Traceback (most recent call last): File " ", line 1, in TypeError: add() takes exactly 2 arguments (1 given) >>> add(1, 2) # 數量一致,通過 3
默認參數是指在定義函數的時候提供一些默認值,如果在調用函數的時候沒有傳遞該參數,則自動使用默認值,否則使用傳遞時該參數的值。
看看例子就明白了:
>>> def add(x, y, z=1): # x, y 是必選參數,z 是默認參數,默認值是 1 ... print x + y + z ... >>> add(1, 2, 3) # 1+2+3 6 >>> add(1, 2) # 沒有傳遞 z,自動使用 z=1,即 1+2+1 4
可以看到,默認參數使用起來也很簡單,但有兩點需要注意的是:
默認參數要放在所有必選參數的后面
默認參數應該使用不可變對象
比如,下面對默認參數的使用是錯誤的:
>>> def add(x=1, y, z): # x 是默認參數,必須放在所有必選參數的后面 ... return x + y + z ... File "", line 1 SyntaxError: non-default argument follows default argument >>> >>> def add(x, y=1, z): # y 是默認參數,必須放在所有必選參數的后面 ... return x + y + z ... File " ", line 1 SyntaxError: non-default argument follows default argument
再來看看為什么默認參數應該使用不可變對象。
我們看一個例子:
>>> def add_to_list(L=[]): ... L.append("END") ... return L
在上面的函數中,L 是一個默認參數,默認值是 [],表示空列表。
我們來看看使用:
>>> add_to_list([1, 2, 3]) # 沒啥問題 [1, 2, 3, "END"] >>> add_to_list(["a", "b", "c"]) # 沒啥問題 ["a", "b", "c", "END"] >>> add_to_list() # 沒有傳遞參數,使用默認值,也沒啥問題 ["END"] >>> add_to_list() # 沒有傳遞參數,使用默認值,竟出現兩個 "END" ["END", "END"] >>> add_to_list() # 糟糕了,三個 "END" ["END", "END", "END"]
為啥呢?我們在調用函數的時候沒有傳遞參數,那么就默認使用 L=[],經過處理,L 應該只有一個元素,怎么會出現調用函數兩次,L 就有兩個元素呢?
原來,L 指向了可變對象 [],當你調用函數時,L 的內容發生了改變,默認參數的內容也會跟著變,也就是,當你第一次調用時,L 的初始值是 [],當你第二次調用時,L 的初始值是 ["END"],等等。
所以,為了避免不必要的錯誤,我們應該使用不可變對象作為函數的默認參數。
可變參數在某些情況下,我們在定義函數的時候,無法預估函數應該制定多少個參數,這時我們就可以使用可變參數了,也就是,函數的參數個數是不確定的。
看看例子:
>>> def add(*numbers): ... sum = 0 ... for i in numbers: ... sum += i ... print "numbers:", numbers ... return sum
在上面的代碼中,numbers 就是一個可變參數,參數前面有一個 * 號,表示是可變的。在函數內部,參數 numbers 接收到的是一個 tuple。
在調用函數時,我們可以給該函數傳遞任意個參數,包括 0 個參數:
>>> add() # 傳遞 0 個參數 numbers: () 0 >>> add(1) # 傳遞 1 個參數 numbers: (1,) 1 >>> add(1, 2) # 傳遞 2 個參數 numbers: (1, 2) 3 >>> add(1, 2, 3) # 傳遞 3 個參數 numbers: (1, 2, 3) 6
上面的 * 表示任意參數,實際上,它還有另外一個用法:用來給函數傳遞參數。
看看例子:
>>> def add(x, y, z): # 有 3 個必選參數 ... return x + y + z ... >>> a = [1, 2, 3] >>> add(a[0], a[1], a[2]) # 這樣傳遞參數很累贅 6 >>> add(*a) # 使用 *a,相當于上面的做法 6 >>> b = (4, 5, 6) >>> add(*b) # 對元組一樣適用 15
再看一個例子:
>>> def add(*numbers): # 函數參數是可變參數 ... sum = 0 ... for i in numbers: ... sum += i ... return sum ... >>> a = [1, 2] >>> add(*a) # 使用 *a 給函數傳遞參數 3 >>> a = [1, 2, 3, 4] >>> add(*a) 10關鍵字參數
可變參數允許你將不定數量的參數傳遞給函數,而關鍵字參數則允許你將不定長度的鍵值對, 作為參數傳遞給一個函數。
讓我們看看例子:
>>> def add(**kwargs): return kwargs >>> add() # 沒有參數,kwargs 為空字典 {} >>> add(x=1) # x=1 => kwargs={"x": 1} {"x": 1} >>> add(x=1, y=2) # x=1, y=2 => kwargs={"y": 2, "x": 1} {"y": 2, "x": 1}
在上面的代碼中,kwargs 就是一個關鍵字參數,它前面有兩個 * 號。kwargs 可以接收不定長度的鍵值對,在函數內部,它會表示成一個 dict。
和可變參數類似,我們也可以使用 **kwargs 的形式來調用函數,比如:
>>> def add(x, y, z): ... return x + y + z ... >>> dict1 = {"z": 3, "x": 1, "y": 6} >>> add(dict1["x"], dict1["y"], dict1["z"]) # 這樣傳參很累贅 10 >>> add(**dict1) # 使用 **dict1 來傳參,等價于上面的做法 10
再看一個例子:
>>> def sum(**kwargs): # 函數參數是關鍵字參數 ... sum = 0 ... for k, v in kwargs.items(): ... sum += v ... return sum >>> sum() # 沒有參數 0 >>> dict1 = {"x": 1} >>> sum(**dict1) # 相當于 sum(x=1) 1 >>> dict2 = {"x": 2, "y": 6} >>> sum(**dict2) # 相當于 sum(x=2, y=6) 8參數組合
在實際的使用中,我們經常會同時用到必選參數、默認參數、可變參數和關鍵字參數或其中的某些。但是,需要注意的是,它們在使用的時候是有順序的,依次是必選參數、默認參數、可變參數和關鍵字參數。
比如,定義一個包含上述四種參數的函數:
>>> def func(x, y, z=0, *args, **kwargs): print "x =", x print "y =", y print "z =", z print "args =", args print "kwargs =", kwargs
在調用函數的時候,Python 會自動按照參數位置和參數名把對應的參數傳進去。讓我們看看:
>>> func(1, 2) # 至少提供兩個參數,因為 x, y 是必選參數 x = 1 y = 2 z = 0 args = () kwargs = {} >>> func(1, 2, 3) # x=1, y=2, z=3 x = 1 y = 2 z = 3 args = () kwargs = {} >>> func(1, 2, 3, 4, 5, 6) # x=1, y=2, z=3, args=(4, 5, 6), kwargs={} x = 1 y = 2 z = 3 args = (4, 5, 6) kwargs = {} >>> func(1, 2, 4, u=6, v=7) # args = (), kwargs = {"u": 6, "v": 7} x = 1 y = 2 z = 4 args = () kwargs = {"u": 6, "v": 7} >>> func(1, 2, 3, 4, 5, u=6, v=7) # args = (4, 5), kwargs = {"u": 6, "v": 7} x = 1 y = 2 z = 3 args = (4, 5) kwargs = {"u": 6, "v": 7}
我們還可以通過下面的形式來傳遞參數:
>>> a = (1, 2, 3) >>> b = {"u": 6, "v": 7} >>> func(*a, **b) x = 1 y = 2 z = 3 args = () kwargs = {"u": 6, "v": 7}小結
默認參數要放在所有必選參數的后面。
應該使用不可變對象作為函數的默認參數。
*args 表示可變參數,**kwargs 表示關鍵字參數。
參數組合在使用的時候是有順序的,依次是必選參數、默認參數、可變參數和關鍵字參數。
*args 和 **kwargs 是 Python 的慣用寫法。
參考資料本文由 funhacks 發表于個人博客,采用 Creative Commons BY-NC-ND 4.0(自由轉載-保持署名-非商用-禁止演繹)協議發布。
非商業轉載請注明作者及出處。商業轉載請聯系作者本人。
本文標題為: Python: 函數參數魔法
本文鏈接為: https://funhacks.net/2016/12/...
args 和 *kwargs · Python進階
函數的參數 - 廖雪峰的官方網站
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44324.html
摘要:本文記錄一些用于代碼計時和簡單性能分析的工具。也就是這個魔法命令把中剩余的代碼作為輸入變量,對其進行計時。該命令會運行最后一個參數指定的代碼,然后在運行時分析所有需要分析的函數。該命令運行之后會打印一個逐行分析報告。 本文記錄一些用于 Python 代碼計時和簡單性能分析的工具。強烈推薦后兩種工具。 begin & end 手動計時 Matlab 里有一對 tic toc 命令,使用格...
摘要:類的繼承類繼承有三種調用方式,其實是有區別的,聽我慢慢道來第一種父類方法參數直接調用第二種方法參數直接調用在誰的類下調用,就找此類對應的下一個就是要繼承的第三種方法參數找類名對應的的下一個,就是繼承的,一般寫本身的類名上下文管理器上下文管理 類的繼承 類繼承有三種調用方式,其實是 有區別 的,聽我慢慢道來 class A: def say(self, name): ...
摘要:什么是元類剛才說了,元類就是創建類的類。類上面的屬性,相信愿意了解元類細節的盆友,都肯定見過這個東西,而且為之好奇。使用了這個魔法方法就意味著就會用指定的元類來創建類了。深刻理解中的元類 (一) python中的類 今天看到一篇好文,然后結合自己的情況總結一波。這里討論的python類,都基于python2.7x以及繼承于object的新式類進行討論。 首先在python中,所有東西都...
摘要:據說,的對象天生擁有一些神奇的方法,它們總被雙下劃線所包圍,他們是面向對象的的一切。的魔術方法非常強大,然而隨之而來的則是責任。 據說,Python 的對象天生擁有一些神奇的方法,它們總被雙下劃線所包圍,他們是面向對象的 Python 的一切。 他們是可以給你的類增加魔力的特殊方法,如果你的對象實現(重載)了這些方法中的某一個,那么這個方法就會在特殊的情況下被 Python 所調用,你...
摘要:幸而,提供了造物主的接口這便是,或者稱為元類。接下來我們將通過一個栗子感受的黑魔法,不過在此之前,我們要先了解一個語法糖。此外,在一些小型的庫中,也有元類的身影。 首發于 我的博客 轉載請注明出處 接觸過 Django 的同學都應該十分熟悉它的 ORM 系統。對于 python 新手而言,這是一項幾乎可以被稱作黑科技的特性:只要你在models.py中隨便定義一個Model的子類,Dj...
閱讀 2907·2021-10-19 10:09
閱讀 3126·2021-10-09 09:41
閱讀 3371·2021-09-26 09:47
閱讀 2687·2019-08-30 15:56
閱讀 590·2019-08-29 17:04
閱讀 979·2019-08-26 11:58
閱讀 2505·2019-08-26 11:51
閱讀 3353·2019-08-26 11:29