轉(zhuǎn)載文章
一、調(diào)用函數(shù)
Python內(nèi)置了很多有用的函數(shù)解虱,我們可以直接調(diào)用攘须。
要調(diào)用一個(gè)函數(shù),需要知道函數(shù)的名稱和參數(shù)殴泰,比如求絕對(duì)值的函數(shù)abs于宙,只有一個(gè)參數(shù)。
也可以在交互式命令行通過(guò)help(abs)查看abs函數(shù)的幫助信息艰匙。
help(abs)
Help on built-in function abs in module builtins:abs(x, /)
Return the absolute value of the argument.
abs(-10)
10
二、定義函數(shù)
在Python中抹恳,定義一個(gè)函數(shù)要使用def語(yǔ)句员凝,依次寫出函數(shù)名、括號(hào)奋献、括號(hào)中的參數(shù)和冒號(hào):健霹,然后,在縮進(jìn)塊中編寫函數(shù)體瓶蚂,函數(shù)的返回值用return語(yǔ)句返回糖埋。
下面我們定義一個(gè)求兩數(shù)之和的函數(shù):
def add_two(a, b):
return a + b
add_two(10, 22)
32
空函數(shù):
def non():
pass
不執(zhí)行任何內(nèi)容,保證程序的正常運(yùn)行窃这。實(shí)際上pass可以用來(lái)作為占位符瞳别,比如現(xiàn)在還沒(méi)想好怎么寫函數(shù)的代碼,就可以先放一個(gè)pass,讓代碼能運(yùn)行起來(lái)祟敛。
請(qǐng)注意疤坝,函數(shù)體內(nèi)部的語(yǔ)句在執(zhí)行時(shí),一旦執(zhí)行到return時(shí)馆铁,函數(shù)就執(zhí)行完畢跑揉,并將結(jié)果返回。因此埠巨,函數(shù)內(nèi)部通過(guò)條件判斷和循環(huán)可以實(shí)現(xiàn)非常復(fù)雜的邏輯历谍。
如果沒(méi)有return語(yǔ)句,函數(shù)執(zhí)行完畢后也會(huì)返回結(jié)果辣垒,只是結(jié)果為None望侈。
return None可以簡(jiǎn)寫為return。
三乍构、函數(shù)的參數(shù)
定義函數(shù)的時(shí)候甜无,我們把參數(shù)的名字和位置確定下來(lái),函數(shù)的接口定義就完成了哥遮。對(duì)于函數(shù)的調(diào)用者來(lái)說(shuō)岂丘,只需要知道如何傳遞正確的參數(shù),以及函數(shù)將返回什么樣的值就夠了眠饮,函數(shù)內(nèi)部的復(fù)雜邏輯被封裝起來(lái)奥帘,調(diào)用者無(wú)需了解。
Python的函數(shù)定義非常簡(jiǎn)單仪召,但靈活度卻非常大寨蹋。除了正常定義的必選參數(shù)外,還可以使用默認(rèn)參數(shù)扔茅、可變參數(shù)和關(guān)鍵字參數(shù)已旧,使得函數(shù)定義出來(lái)的接口,不但能處理復(fù)雜的參數(shù)召娜,還可以簡(jiǎn)化調(diào)用者的代碼运褪。
3.1 默認(rèn)參數(shù)
# 求x的平方
def power(x):
return x * x
power(5)
25
# 求x的n次冪,設(shè)置n的默認(rèn)值為2。
def power(x, n=2):
return x ** n
power(5, 3)
125
設(shè)置默認(rèn)參數(shù)時(shí)玖瘸,有幾點(diǎn)要注意:
必選參數(shù)在前秸讹,默認(rèn)參數(shù)在后,否則Python的解釋器會(huì)報(bào)錯(cuò)(思考一下為什么默認(rèn)參數(shù)不能放在必選參數(shù)前面)雅倒;
如何設(shè)置默認(rèn)參數(shù)璃诀。
當(dāng)函數(shù)有多個(gè)參數(shù)時(shí),把變化大的參數(shù)放前面蔑匣,變化小的參數(shù)放后面劣欢。變化小的參數(shù)就可以作為默認(rèn)參數(shù)棕诵。
使用默認(rèn)參數(shù)有什么好處?最大的好處是能降低調(diào)用函數(shù)的難度氧秘。
3.2 可變參數(shù)
在Python函數(shù)中年鸳,還可以定義可變參數(shù)。顧名思義丸相,可變參數(shù)就是傳入的參數(shù)個(gè)數(shù)是可變的搔确,可以是1個(gè)、2個(gè)到任意個(gè)灭忠,還可以是0個(gè)膳算。
我們以數(shù)學(xué)題為例子,給定一組數(shù)字a弛作、b涕蜂、c請(qǐng)計(jì)算a+b+c....
要定義出這個(gè)函數(shù),我們必須確定輸入的參數(shù)映琳。由于參數(shù)個(gè)數(shù)不確定机隙,我們首先想到可以把a(bǔ),b萨西,c……作為一個(gè) list 或 tuple 傳進(jìn)來(lái)有鹿,這樣,函數(shù)可以定義如下:
def calc(numbers):
amount = 0
for num in numbers:
amount += num
return amount
numbers = [100, 200, 3, 4]
calc(numbers)
307
但是調(diào)用的時(shí)候谎脯,需要先組裝出一個(gè)list或tuple:calc([1, 2, 3])
或者calc(numbers)
如果利用可變參數(shù)葱跋,我們把函數(shù)的參數(shù)改為可變參數(shù):簡(jiǎn)化
def calc(*numbers):
amount = 0
for num in numbers:
amount += num
return amount
calc(1,2,3,4,5,7)
22
已經(jīng)有一個(gè)list或者tuple,要調(diào)用一個(gè)可變參數(shù)怎么辦源梭?可以這樣做:
>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14
這種寫法當(dāng)然是可行的娱俺,問(wèn)題是太繁瑣,所以Python允許你在list或tuple前面加一個(gè)*號(hào)废麻,把list或tuple的元素變成可變參數(shù)傳進(jìn)去:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
*nums表示把nums這個(gè)list的所有元素作為可變參數(shù)傳進(jìn)去荠卷。這種寫法相當(dāng)有用,而且很常見(jiàn)烛愧。
3.3 關(guān)鍵字參數(shù)
可變參數(shù)允許你傳入 0 個(gè)或任意個(gè)參數(shù)油宜,這些可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè) tuple。而關(guān)鍵字參數(shù)允許你傳入 0 個(gè)或任意個(gè)含參數(shù)名的參數(shù)屑彻,這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè) dict验庙。
def get_kwargs(**kwargs):
print(kwargs)
get_kwargs(a=10, b="hello", c=['a', 1, 'bcd'])
{'a': 10, 'b': 'hello', 'c': ['a', 1, 'bcd']}
或者
temp={'a': 10, 'b': 'hello', 'c': ['a', 1, 'bcd']}
get_kwargs(**temp)
但無(wú)法限制關(guān)鍵詞的名字顶吮,例如只需要city和addr社牲,
person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
我們不希望有不受限制的關(guān)鍵字參數(shù)zipcode
如果要限制關(guān)鍵字參數(shù)的名字,就可以用命名關(guān)鍵字參數(shù)悴了,例如搏恤,只接收city和job作為關(guān)鍵字參數(shù)违寿。這種方式定義的函數(shù)如下:
def person(name, age, *, city, job):
print(name, age, city, job)
和關(guān)鍵字參數(shù)**kw不同,命名關(guān)鍵字參數(shù)需要一個(gè)特殊分隔符*熟空,*后面的參數(shù)被視為命名關(guān)鍵字參數(shù)藤巢。
調(diào)用方式如下:
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
如果函數(shù)定義中已經(jīng)有了一個(gè)可變參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符*了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名息罗,這和位置參數(shù)不同掂咒。如果沒(méi)有傳入?yún)?shù)名,調(diào)用將報(bào)錯(cuò):
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given
由于調(diào)用時(shí)缺少參數(shù)名city和job迈喉,Python解釋器把這4個(gè)參數(shù)均視為位置參數(shù)绍刮,但person()函數(shù)僅接受2個(gè)位置參數(shù)。
命名關(guān)鍵字參數(shù)可以有缺省值挨摸,從而簡(jiǎn)化調(diào)用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
由于命名關(guān)鍵字參數(shù)city具有默認(rèn)值孩革,調(diào)用時(shí),可不傳入city參數(shù):
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer
使用命名關(guān)鍵字參數(shù)時(shí)得运,要特別注意膝蜈,如果沒(méi)有可變參數(shù),就必須加一個(gè)*作為特殊分隔符熔掺。如果缺少*饱搏,Python解釋器將無(wú)法識(shí)別位置參數(shù)和命名關(guān)鍵字參數(shù):
def person(name, age, city, job):
# 缺少 *,city和job被視為位置參數(shù)
pass
3.4 混合參數(shù)
在Python中定義函數(shù)瞬女,可以用必選參數(shù)窍帝、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)诽偷,這4種參數(shù)都可以一起使用坤学,或者只用其中某些,但是請(qǐng)注意报慕,參數(shù)定義的順序必須是:必選參數(shù)深浮、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)眠冈。
def func(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
func(10, 20, 30, 'd', 'e', 'f', x=99, y ='hello')
a = 10 b = 20 c = 30 args = ('d', 'e', 'f') kw = {'y': 'hello', 'x': 99}
四 飞苇、匿名函數(shù) lambda
python 使用 lambda 來(lái)創(chuàng)建匿名函數(shù)。
lambda只是一個(gè)表達(dá)式蜗顽,函數(shù)體比def簡(jiǎn)單很多布卡。
lambda的主體是一個(gè)表達(dá)式,而不是一個(gè)代碼塊雇盖。僅僅能在lambda表達(dá)式中封裝有限的邏輯進(jìn)去忿等。
lambda函數(shù)擁有自己的名字空間,且不能訪問(wèn)自有參數(shù)列表之外或全局名字空間里的參數(shù)崔挖。
雖然lambda函數(shù)看起來(lái)只能寫一行贸街,卻不等同于C或C++的內(nèi)聯(lián)函數(shù)庵寞,后者的目的是調(diào)用小函數(shù)時(shí)不占用棧內(nèi)存從而增加運(yùn)行效率。
# 定義lambda函數(shù)
f = lambda x: x*x
[f(i) for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
小結(jié)
Python的函數(shù)具有非常靈活的參數(shù)形態(tài)薛匪,既可以實(shí)現(xiàn)簡(jiǎn)單的調(diào)用捐川,又可以傳入非常復(fù)雜的參數(shù)。
默認(rèn)參數(shù)一定要用不可變對(duì)象逸尖,如果是可變對(duì)象古沥,運(yùn)行會(huì)有邏輯錯(cuò)誤!
要注意定義可變參數(shù)和關(guān)鍵字參數(shù)的語(yǔ)法:
*args是可變參數(shù)娇跟,args接收的是一個(gè)tuple渐白;
**kw是關(guān)鍵字參數(shù),kw接收的是一個(gè)dict逞频。
以及調(diào)用函數(shù)時(shí)如何傳入可變參數(shù)和關(guān)鍵字參數(shù)的語(yǔ)法:
可變參數(shù)既可以直接傳入:func(1, 2, 3)纯衍,又可以先組裝list或tuple,再通過(guò)args傳入:func((1, 2, 3))苗胀;
關(guān)鍵字參數(shù)既可以直接傳入:func(a=1, b=2)襟诸,又可以先組裝dict,再通過(guò)kw傳入:func({'a': 1, 'b': 2})基协。
使用args和*kw是Python的習(xí)慣寫法歌亲,當(dāng)然也可以用其他參數(shù)名,但最好使用習(xí)慣用法澜驮。