上篇文章已經(jīng)詳細(xì)的介紹了python函數(shù)的傳參方式轧拄,本文接著上文的內(nèi)容詳細(xì)的講解一下可變參數(shù) *args **kwargs慕购,
- 本文主要內(nèi)容:
- 可變參數(shù)的定義
- 理解參數(shù)傳遞(*)星號(hào)
- *args 非鍵值可變參數(shù)的定義
- 理解參數(shù)傳遞(**)雙星號(hào)
- **kwargs 鍵值可變參數(shù)的定義
- 可變參數(shù)的混合調(diào)用和定義
1.可變參數(shù)定義
定義函數(shù)時(shí)鲫尊,有時(shí)候我們不確定調(diào)用的時(shí)候會(huì)多少個(gè)參數(shù),就可以使用可變參數(shù)
def func(required_arg, default_arg=None, *args, **kwargs):
pass
# required_arg 必傳位置參數(shù)
# default_arg 默認(rèn)參數(shù)
# *args 非鍵值可變參數(shù)
# **kwargs 鍵值可變參數(shù)
上面是Python得一個(gè)典型的函數(shù)定義,簡單明了的表述了python的四種參數(shù)定義方式
- required_arg 必傳位置參數(shù)
- default_arg 默認(rèn)參數(shù)
- *args 非鍵值可變參數(shù)
- **kwargs 鍵值可變參數(shù)
注意:這幾種參數(shù)是有順序的傅是,位置參數(shù) > 默認(rèn)參數(shù)>非鍵值可變參數(shù)>鍵值可變參數(shù)
今天主要介紹可變參數(shù):
Python有一個(gè)特殊的語法,(單星號(hào))(雙星號(hào)),允許您將數(shù)量可變的參數(shù)傳遞給函數(shù)沮尿。 約定俗成的方式通常寫args和kwargs, args和kwargs 只是變量名,你可以寫vars和*vars實(shí)現(xiàn)相同的結(jié)果空凸。
*args是用來傳遞一個(gè)非鍵值變長參數(shù)列表功能嚎花。
**kwargs通常用來傳遞關(guān)鍵字變長參數(shù)。
2. 理解參數(shù)傳遞(*)星號(hào)
>>> def add(x, y):
... print("x:",x)
... print("y:",y)
... print("sum:", x+y)
上面定義一個(gè)簡單的函數(shù)add劫恒,我們通常的調(diào)用方式
>>> add(1, 2)
x: 1
y: 2
sum: 3
>>> add(x=1, y=2)
x: 1
y: 2
sum: 3
當(dāng)面我們多傳或者少傳參數(shù)程序就會(huì)拋出異常
>>> add(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'y'
>>> add(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
如果我們想通過1個(gè)變量傳入多個(gè)參數(shù)怎么傳贩幻?
>>> nums = (1,2)
>>> add(nums)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'y'
我們把參數(shù)值封裝到一個(gè)tuple 中轿腺,然后直接傳遞到add 中程序拋出了異常參數(shù)缺失,那要如何傳參丛楚,可以使用*號(hào)
>>> nums = (1,2)
>>> add(*nums)
x: 1
y: 2
sum: 3
>>> nums = (1,2,3)
>>> add(*nums)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
通過上面執(zhí)行結(jié)果可以做到族壳,只要在nums前加上,并且nums 的數(shù)量跟參數(shù)一致就可以調(diào)用成功,這是什么原因趣些?
這里有一個(gè)知識(shí)點(diǎn)叫做序列化解包仿荆,在傳遞元組時(shí),讓元組的每一個(gè)元素對(duì)應(yīng)一個(gè)位置參數(shù)坏平,當(dāng)nums 傳遞到函數(shù)里面時(shí)拢操,程序會(huì)自動(dòng)解包映射到位置參數(shù)上
3. *args 非鍵值可變參數(shù)的定義
我們?cè)诙x函數(shù)時(shí),發(fā)現(xiàn)不能確認(rèn)非鍵值參數(shù)的個(gè)數(shù)的時(shí)候舶替,我們就可以定義為可變非鍵值參數(shù)
def add(*args):
... sum = 0
... for arg in args: #args是個(gè)元組
... print(arg)
... sum += arg
... print("sum:", sum)
我們通過*args 代表接收一個(gè)可變參數(shù)列表令境,那如何調(diào)用可變參數(shù)列表的函數(shù)呢
>>> add() #不傳參數(shù)
sum: 0
>>> add(1,2,3)#通過位置參數(shù)傳遞
1
2
3
sum: 6
>>> nums = (1,2,3)#通過元祖或者列表 加* 傳遞
>>> add(*nums)
1
2
3
sum: 6
從上面的調(diào)用方式
args 定義的函數(shù),可以傳0個(gè)或者-個(gè)以上參數(shù)顾瞪,可以通過位置參數(shù)傳遞舔庶,也可以傳遞
位置參數(shù)和可變參數(shù)*args 的解包關(guān)系
def add(num, *args):
... print("num:", num)
... sum = 0
... for arg in args: #args是個(gè)元組
... print(arg)
... sum += arg
... print("sum:", sum)
當(dāng)我們不傳參數(shù)的時(shí)候,程序會(huì)報(bào)錯(cuò)陈醒,因?yàn)榈谝粋€(gè)是必傳位置參數(shù)惕橙,所以不傳會(huì)拋出異常
>>> add()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'num'
當(dāng)我們傳遞一個(gè)參數(shù)的時(shí)候,程序正常執(zhí)行钉跷,num 獲取到傳入的參數(shù)值弥鹦,args 沒有取到值
>>> add(1)
num: 1
sum: 0
當(dāng)我們傳遞二個(gè)參數(shù)的時(shí)候,程序正常執(zhí)行爷辙,num 獲取到第一個(gè)參數(shù)值彬坏,args 取到第二參數(shù)
>>> add(1, 2)
num: 1
2
sum: 2
當(dāng)我們傳遞三個(gè)參數(shù)的時(shí)候,程序正常執(zhí)行犬钢,num 獲取到第一個(gè)參數(shù)值苍鲜,args 取到第一個(gè)以后參數(shù)
>>> add(1, 2, 3)
num: 1
2
3
sum: 5
當(dāng)我們傳遞一個(gè)元祖的時(shí)候,程序正常執(zhí)行玷犹,num 獲取到第一個(gè)參數(shù)值,args 取到第一個(gè)以后參數(shù)
>>> nums = (1,2,3)
>>> add(*nums)
num: 1
2
3
sum: 5
由上可知洒疚,在使用args 定義函數(shù)時(shí)候歹颓,如果可變參數(shù)(args)之前有位置參數(shù),解包參數(shù)會(huì)優(yōu)先賦值給位置參數(shù)油湖,剩余的變量賦值給可變參數(shù)
理解參數(shù)傳遞(**)雙星號(hào)
>>> def fun(x, y, z):
... print("x:", x)
... print("y:", y)
... print("z:", z)
...
>>> fun(1,2,3)
x: 1
y: 2
z: 3
>>> fun(x=1,y=2,z=3)
x: 1
y: 2
z: 3
>>> fun(1,y=2,z=3)
x: 1
y: 2
z: 3
調(diào)用函數(shù)func 我們可以通過以上方式傳參巍扛,我們還能有其他方式嗎?有乏德,那就是通過**
>>> nums = {"x":1,"y":2, "z":3}
>>> fun(**nums)
x: 1
y: 2
z: 3
>>> nums = {"y":2, "z":3}
>>> fun(1, **nums)
x: 1
y: 2
z: 3
我們可以把參數(shù)封裝成字典撤奸,然后通過**nums 的方式傳給函數(shù)func吠昭,實(shí)現(xiàn)原理是啥?
* 是解包賦值給位置參數(shù)
** 是解包賦值給關(guān)鍵詞參數(shù)(關(guān)鍵詞參數(shù)參考前文)
**kwargs 鍵值可變參數(shù)的定義
用”**kwargs”定義函數(shù),kwargs接收除常規(guī)參數(shù)列表以外的鍵值參數(shù)字典
如果我們需要傳遞鍵值可變參數(shù)就如下定義函數(shù)
def func(**kwargs):
>>> def func(**kwargs):
... for key, value in kwargs.items(): #kwargs 是一個(gè)字典
... print("key:", key, " value:", value)
...
我們通過**kwargs代表接收一個(gè)可變參數(shù)字典胧瓜,那如何調(diào)用可變參數(shù)字典的函數(shù)呢
>>> func(a=1,b=2)
key: a value: 1
key: b value: 2
>>> nums = {"a": 1, "b": 2}
>>> func(**nums)
key: a value: 1
key: b value: 2
從上面的調(diào)用方式
**kwargs 定義的函數(shù)矢棚,可以通過關(guān)鍵詞參數(shù)傳遞,也可以**字典傳遞
6. 可變參數(shù)的混合調(diào)用和定義
位置參數(shù)府喳、默認(rèn)參數(shù)蒲肋、可變參數(shù)的混合使用,基本原則是:先位置參數(shù)钝满,默認(rèn)參數(shù)兜粘, 非鍵值可變參數(shù)(args),鍵值可變參數(shù)(kwargs)
def func(required_arg, default_arg=None, *args, **kwargs):
pass
# required_arg 必傳位置參數(shù)
# default_arg 默認(rèn)參數(shù)
# *args 非鍵值可變參數(shù)
# **kwargs 鍵值可變參數(shù)
args和*kwargs 的區(qū)別
>>> def func(*args, **kwargs):
... print("args:", args)
... print("kwargs", kwargs)
...
>>> func(1,2)
args: (1, 2)
kwargs {}
>>> func(a=1, b=2)
args: ()
kwargs {'a': 1, 'b': 2}
>>> func(1,2,a=1, b=2)
args: (1, 2)
kwargs {'a': 1, 'b': 2}
可以看到弯蚜,*args
表示任何多個(gè)非鍵值參數(shù)孔轴,它是一個(gè)tuple;**kwargs
表示關(guān)鍵字參數(shù)碎捺,它是一個(gè)dict路鹰。并且同時(shí)使用*args
和**kwargs
時(shí),必須*args
參數(shù)列要在**kwargs
前牵寺,像func(a=1, b='2',1,2 )
這樣調(diào)用的話悍引,會(huì)提示語法錯(cuò)誤“SyntaxError: non-keyword arg after keyword arg”
*args與位置參數(shù)和默認(rèn)參數(shù)混用
args與位置參數(shù)和默認(rèn)參數(shù)混用:args要放到位置參數(shù)后
def func(a, *args, b=1):
... print("a:", a)
... print("b:", b)
... print("args:", args)
...
**kwargs與位置參數(shù)和默認(rèn)參數(shù)混用
**kwargs 要放在默認(rèn)參數(shù)之后
正確定義
def func(a, b=1,**kwargs):
... print("a:", a)
... print("b:", b)
... print("args:", args)
...
錯(cuò)誤定義
def func(a, **kwargs, b=1):
... print("a:", a)
... print("b:", b)
... print("args:", args)
...
SyntaxError: invalid syntax
總結(jié)
了解函數(shù)4種參數(shù)傳遞方式帽氓,位置參數(shù)趣斤,關(guān)鍵詞參數(shù),默認(rèn)參數(shù)黎休,可變參數(shù)
理解*(單星號(hào))浓领,**(雙星號(hào))的傳參方式
* args和** kwargs是特殊關(guān)鍵字函數(shù)可以將可變長度參數(shù)。
* args通過數(shù)量可變的non-keyworded參數(shù)列表和列表的操作可以執(zhí)行势腮。
* * kwargs通過變量數(shù)量的關(guān)鍵字參數(shù)字典功能字典可以執(zhí)行的操作联贩。
注意:不同的類型的參數(shù)定義和傳遞都是有順序要求的