python:函數(shù)說明

Python: 函數(shù)參數(shù)魔法

2016-12-01

函數(shù)參數(shù)

在 Python 中,定義函數(shù)和調(diào)用函數(shù)都很簡單局义,但如何定義函數(shù)參數(shù)和傳遞函數(shù)參數(shù),則涉及到一些套路了檩帐。總的來說诅挑,Python 的函數(shù)參數(shù)主要分為以下幾種:

必選參數(shù)

默認(rèn)參數(shù)

可變參數(shù)

關(guān)鍵字參數(shù)

必選參數(shù)

必選參數(shù)可以說是最常見的了拔妥,顧名思義没龙,必選參數(shù)就是在調(diào)用函數(shù)的時候要傳入數(shù)量一致的參數(shù)兜畸,比如:

1

2

3

4

5

6

7

8

9

10

11

12

13

>>> def add(x, y): ? ? ? ?# x, y 是必選參數(shù)

... ? ? 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) ? ? ? ? ? ? # 數(shù)量一致恩沛,通過

3

默認(rèn)參數(shù)

默認(rèn)參數(shù)是指在定義函數(shù)的時候提供一些默認(rèn)值芒珠,如果在調(diào)用函數(shù)的時候沒有傳遞該參數(shù)皱卓,則自動使用默認(rèn)值部逮,否則使用傳遞時該參數(shù)的值。

看看例子就明白了:

1

2

3

4

5

6

7

>>> def add(x, y, z=1): ? ? # x, y 是必選參數(shù)掐禁,z 是默認(rèn)參數(shù)缕允,默認(rèn)值是 1

... ? ? print x + y + z

...

>>> add(1, 2, 3) ? ? ? ? ? ?# 1+2+3

6

>>> add(1, 2) ? ? ? ? ? ? ? # 沒有傳遞 z障本,自動使用 z=1般又,即 1+2+1

4

可以看到茴迁,默認(rèn)參數(shù)使用起來也很簡單堕义,但有兩點(diǎn)需要注意的是:

默認(rèn)參數(shù)要放在所有必選參數(shù)的后面

默認(rèn)參數(shù)應(yīng)該使用不可變對象

比如倦卖,下面對默認(rèn)參數(shù)的使用是錯誤的:

1

2

3

4

5

6

7

8

9

10

11

>>> def add(x=1, y, z): ? ? ?# x 是默認(rèn)參數(shù)怕膛,必須放在所有必選參數(shù)的后面

... ? ? return x + y + z

...

?File "", line 1

SyntaxError: non-default argument follows default argument

>>>

>>> def add(x, y=1, z): ? ? ?# y 是默認(rèn)參數(shù)褐捻,必須放在所有必選參數(shù)的后面

... ? ? return x + y + z

...

?File "", line 1

SyntaxError: non-default argument follows default argument

再來看看為什么默認(rèn)參數(shù)應(yīng)該使用不可變對象。

我們看一個例子:

1

2

3

>>> def add_to_list(L=[]):

... ? ? L.append('END')

... ? ? return L

在上面的函數(shù)中景馁,L 是一個默認(rèn)參數(shù)绰精,默認(rèn)值是 []透葛,表示空列表阱表。

我們來看看使用:

1

2

3

4

5

6

7

8

9

10

>>> add_to_list([1, 2, 3]) ? ? ? ? ?# 沒啥問題

[1, 2, 3, 'END']

>>> add_to_list(['a', 'b', 'c']) ? ?# 沒啥問題

['a', 'b', 'c', 'END']

>>> add_to_list() ? ? ? ? ? ? ? ? ? # 沒有傳遞參數(shù)涉馁,使用默認(rèn)值烤送,也沒啥問題

['END']

>>> add_to_list() ? ? ? ? ? ? ? ? ? # 沒有傳遞參數(shù)帮坚,使用默認(rèn)值试和,竟出現(xiàn)兩個 'END'

['END', 'END']

>>> add_to_list() ? ? ? ? ? ? ? ? ? # 糟糕了,三個 'END'

['END', 'END', 'END']

為啥呢纫普?我們在調(diào)用函數(shù)的時候沒有傳遞參數(shù)阅悍,那么就默認(rèn)使用 L=[],經(jīng)過處理昨稼,L 應(yīng)該只有一個元素节视,怎么會出現(xiàn)調(diào)用函數(shù)兩次,L 就有兩個元素呢假栓?

原來寻行,L 指向了可變對象 [],當(dāng)你調(diào)用函數(shù)時匾荆,L 的內(nèi)容發(fā)生了改變拌蜘,默認(rèn)參數(shù)的內(nèi)容也會跟著變,也就是,當(dāng)你第一次調(diào)用時,L 的初始值是 [],當(dāng)你第二次調(diào)用時链蕊,L 的初始值是 ['END']陪蜻,等等症昏。

所以础米,為了避免不必要的錯誤,我們應(yīng)該使用不可變對象作為函數(shù)的默認(rèn)參數(shù)竖瘾。

可變參數(shù)

在某些情況下庸论,我們在定義函數(shù)的時候,無法預(yù)估函數(shù)應(yīng)該制定多少個參數(shù)趋观,這時我們就可以使用可變參數(shù)了麸恍,也就是瓤球,函數(shù)的參數(shù)個數(shù)是不確定的欠肾。

看看例子:

1

2

3

4

5

6

>>> def add(*numbers):

... ? ? sum = 0

... ? ? for i in numbers:

... ? ? ? ? sum += i

... ? ? print 'numbers:', numbers

... ? ? return sum

在上面的代碼中瑟慈,numbers 就是一個可變參數(shù),參數(shù)前面有一個 * 號,表示是可變的。在函數(shù)內(nèi)部堆生,參數(shù) numbers 接收到的是一個 tuple。

在調(diào)用函數(shù)時桥温,我們可以給該函數(shù)傳遞任意個參數(shù)氛谜,包括 0 個參數(shù):

1

2

3

4

5

6

7

8

9

10

11

12

>>> add() ? ? ? ? ? # 傳遞 0 個參數(shù)

numbers: ()

0

>>> add(1) ? ? ? ? ?# 傳遞 1 個參數(shù)

numbers: (1,)

1

>>> add(1, 2) ? ? ? # 傳遞 2 個參數(shù)

numbers: (1, 2)

3

>>> add(1, 2, 3) ? ?# 傳遞 3 個參數(shù)

numbers: (1, 2, 3)

6

上面的 * 表示任意參數(shù)悔政,實(shí)際上芦瘾,它還有另外一個用法:用來給函數(shù)傳遞參數(shù)。

看看例子:

1

2

3

4

5

6

7

8

9

10

11

>>> def add(x, y, z): ? ? ? ?# 有 3 個必選參數(shù)

... return x + y + z

...

>>> a = [1, 2, 3]

>>> add(a[0], a[1], a[2]) ? ?# 這樣傳遞參數(shù)很累贅

6

>>> add(*a) ? ? ? ? ? ? ? ? ?# 使用 *a,相當(dāng)于上面的做法

6

>>> b = (4, 5, 6)

>>> add(*b) ? ? ? ? ? ? ? ? ?# 對元組一樣適用

15

再看一個例子:

1

2

3

4

5

6

7

8

9

10

11

12

>>> def add(*numbers): ? ? ? # 函數(shù)參數(shù)是可變參數(shù)

... sum = 0

... for i in numbers:

... ? ?sum += i

... return sum

...

>>> a = [1, 2]

>>> add(*a) ? ? ? ? ? ? ? ? ?# 使用 *a 給函數(shù)傳遞參數(shù)

3

>>> a = [1, 2, 3, 4]

>>> add(*a)

10

關(guān)鍵字參數(shù)

可變參數(shù)允許你將不定數(shù)量的參數(shù)傳遞給函數(shù)哄陶,而關(guān)鍵字參數(shù)則允許你將不定長度的鍵值對, 作為參數(shù)傳遞給一個函數(shù)。

讓我們看看例子:

1

2

3

4

5

6

7

8

>>> def add(**kwargs):

? ?return kwargs

>>> add() ? ? ? ? ? ?# 沒有參數(shù),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 就是一個關(guān)鍵字參數(shù)歇竟,它前面有兩個 * 號馋记。kwargs 可以接收不定長度的鍵值對壁肋,在函數(shù)內(nèi)部,它會表示成一個 dict。

和可變參數(shù)類似阁吝,我們也可以使用 **kwargs 的形式來調(diào)用函數(shù),比如:

1

2

3

4

5

6

7

8

>>> 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

再看一個例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

>>> def sum(**kwargs): ? ? ? ? ? ? ? # 函數(shù)參數(shù)是關(guān)鍵字參數(shù)

... sum = 0

... for k, v in kwargs.items():

... ? ?sum += v

... return sum

>>> sum() ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 沒有參數(shù)

0

>>> dict1 = {'x': 1}

>>> sum(**dict1) ? ? ? ? ? ? ? ? ? ? # 相當(dāng)于 sum(x=1)

1

>>> dict2 = {'x': 2, 'y': 6}

>>> sum(**dict2) ? ? ? ? ? ? ? ? ? ? # 相當(dāng)于 sum(x=2, y=6)

8

參數(shù)組合

在實(shí)際的使用中,我們經(jīng)常會同時用到必選參數(shù)装盯、默認(rèn)參數(shù)坷虑、可變參數(shù)和關(guān)鍵字參數(shù)或其中的某些。但是埂奈,需要注意的是迄损,它們在使用的時候是有順序的,依次是必選參數(shù)账磺、默認(rèn)參數(shù)芹敌、可變參數(shù)和關(guān)鍵字參數(shù)痊远。

比如,定義一個包含上述四種參數(shù)的函數(shù):

1

2

3

4

5

6

>>> def func(x, y, z=0, *args, **kwargs):

? ?print 'x =', x

? ?print 'y =', y

? ?print 'z =', z

? ?print 'args =', args

? ?print 'kwargs =', kwargs

在調(diào)用函數(shù)的時候氏捞,Python 會自動按照參數(shù)位置和參數(shù)名把對應(yīng)的參數(shù)傳進(jìn)去碧聪。讓我們看看:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

>>> func(1, 2) ? ? ? ? ? ? ? ? ? ? # 至少提供兩個參數(shù),因為 x, y 是必選參數(shù)

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}

我們還可以通過下面的形式來傳遞參數(shù):

1

2

3

4

5

6

7

8

>>> a = (1, 2, 3)

>>> b = {'u': 6, 'v': 7}

>>> func(*a, **b)

x = 1

y = 2

z = 3

args = ()

kwargs = {'u': 6, 'v': 7}

小結(jié)

默認(rèn)參數(shù)要放在所有必選參數(shù)的后面液茎。

應(yīng)該使用不可變對象作為函數(shù)的默認(rèn)參數(shù)逞姿。

*args 表示可變參數(shù),**kwargs 表示關(guān)鍵字參數(shù)捆等。

參數(shù)組合在使用的時候是有順序的滞造,依次是必選參數(shù)、默認(rèn)參數(shù)栋烤、可變參數(shù)和關(guān)鍵字參數(shù)。

*args 和 **kwargs 是 Python 的慣用寫法明郭。

參考資料

args 和 *kwargs · Python進(jìn)階

函數(shù)的參數(shù) - 廖雪峰的官方網(wǎng)站

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝴光,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子达址,更是在濱河造成了極大的恐慌蔑祟,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沉唠,死亡現(xiàn)場離奇詭異疆虚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)满葛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門径簿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘀韧,你說我怎么就攤上這事篇亭。” “怎么了锄贷?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵译蒂,是天一觀的道長。 經(jīng)常有香客問我谊却,道長柔昼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任炎辨,我火速辦了婚禮捕透,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己乙嘀,他們只是感情好末购,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著虎谢,像睡著了一般盟榴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘉冒,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天曹货,我揣著相機(jī)與錄音,去河邊找鬼讳推。 笑死顶籽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的银觅。 我是一名探鬼主播礼饱,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼究驴!你這毒婦竟也來了镊绪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤洒忧,失蹤者是張志新(化名)和其女友劉穎蝴韭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熙侍,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡榄鉴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛉抓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庆尘。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巷送,靈堂內(nèi)的尸體忽然破棺而出驶忌,到底是詐尸還是另有隱情,我是刑警寧澤笑跛,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布付魔,位于F島的核電站,受9級特大地震影響堡牡,放射性物質(zhì)發(fā)生泄漏抒抬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一晤柄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妖胀,春花似錦芥颈、人聲如沸惠勒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纠屋。三九已至,卻和暖如春盾计,著一層夾襖步出監(jiān)牢的瞬間售担,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工署辉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留族铆,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓哭尝,卻偏偏與公主長得像哥攘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子材鹦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容