函數(shù)
函數(shù)是程序中可復(fù)用的代碼塊食磕。你可以給這段代碼塊起名字输莺,也就是函數(shù)名。然后在程序中的任意地方去調(diào)用它项栏。我們已經(jīng)使用過(guò)內(nèi)置的一些函數(shù)浦辨,比如range()
, len()
。
函數(shù)也許是成功軟件里最重要的一個(gè)組成部分沼沈,下面我們將會(huì)詳述函數(shù)的各個(gè)部分流酬。
函數(shù)使用關(guān)鍵字def
來(lái)定義,緊跟著關(guān)鍵字的是函數(shù)名列另,后面的一對(duì)小括號(hào)里有保存?zhèn)魅雲(yún)?shù)的變量芽腾,在這一行的最后有個(gè)冒號(hào),表示下面的語(yǔ)句塊屬于該函數(shù)页衙。下面是一個(gè)簡(jiǎn)單的例子:
例子(保存至function1.py
):
def say_hello():
#屬于函數(shù)的語(yǔ)句塊
print('你好摊滔,中國(guó)!')
say_hello()#調(diào)用函數(shù)
say_hello()#調(diào)用函數(shù)
輸出:
$ python function1.py
你好阴绢,中國(guó)!
你好艰躺,中國(guó)呻袭!
它是怎么運(yùn)作的呢?
我們定義了一個(gè)函數(shù)say_hello()
,然后調(diào)用了兩次腺兴。該函數(shù)沒(méi)有傳入?yún)?shù)左电,因此括號(hào)里沒(méi)有變量。參數(shù)是函數(shù)的輸入含长,因此我們可以傳入不同的值券腔,然后得到不同的返回值。
注意拘泞,我們調(diào)用了兩次函數(shù)纷纫,也就是說(shuō),不用重復(fù)寫(xiě)代碼了陪腌!
函數(shù)參數(shù)
函數(shù)可以接收多個(gè)參數(shù)辱魁,也就是你提供給函數(shù)的變量,函數(shù)可以使用這些變量诗鸭,完成某個(gè)功能染簇。參數(shù)和變量不同之處 - 參數(shù)直到調(diào)用函數(shù)的時(shí)候才會(huì)被賦值。
在函數(shù)定義的時(shí)候强岸,參數(shù)用小括號(hào)括住锻弓,參數(shù)之間用逗號(hào)分隔。當(dāng)要調(diào)用該函數(shù)時(shí)蝌箍,要類(lèi)似的提供參數(shù)值青灼。注意,我們這里用的專(zhuān)業(yè)術(shù)語(yǔ)-在定義函數(shù)時(shí)妓盲,括號(hào)里的叫做參數(shù)杂拨,在調(diào)用函數(shù)時(shí),括號(hào)里的叫做參數(shù)值悯衬。
例子(保存至function_param.py
):
def print_max(a, b):
if a > b:
print(a, '第一個(gè)數(shù)大弹沽。')
elif a == b:
print('兩個(gè)數(shù)一樣大。')
else:
print(b, '第二個(gè)數(shù)大筋粗。')
print_max(3, 4)
x = 6
y = 7
print_max(x, y)
輸出:
$ python function_param.py
4 第二個(gè)數(shù)大策橘。
7 第二個(gè)數(shù)大。
它是怎么運(yùn)作的呢亏狰?
我們定義了一個(gè)叫做print_max
的函數(shù)役纹,該函數(shù)有兩個(gè)參數(shù)a
和b
。我們用if語(yǔ)句去找到兩個(gè)數(shù)中較大的一個(gè)數(shù)暇唾,然后把它打印出來(lái)促脉。
第一次調(diào)用print_max
辰斋,我們直接把數(shù)值當(dāng)作參數(shù)值;第二次調(diào)用print_max
瘸味,我們把變量當(dāng)作參數(shù)值宫仗,print_max(x, y)
把x的值賦給a,把y的值賦給b旁仿。兩種情況下藕夫,print_max
函數(shù)有著相同的運(yùn)作方式。
局部變量
你在函數(shù)里定義的變量枯冈,與函數(shù)外的同名變量沒(méi)有任何關(guān)系毅贮;也就是說(shuō),對(duì)于函數(shù)尘奏,變量名是局部的滩褥。這種情況叫做變量的作用域。變量在哪里代碼塊里定義的炫加,它的作用域就在哪個(gè)代碼塊里, 變量作用域從定義的地方開(kāi)始瑰煎,直到代碼塊的結(jié)束位置。
例子(保存至function_local.py
):
x = 50
def func(x):
print('x 的值:', x)
x = 2
print('變成局部變量x的值:', x)
func(x)
print('外部x的值:', x)
輸出:
$ python function_local.py
x 的值: 50
變成局部變量x的值: 2
外部x的值: 50
它是怎么運(yùn)作的呢俗孝?
第一次打印的x值酒甸,在函數(shù)體的第一行,它用主代碼塊傳進(jìn)的參數(shù)值赋铝。
接下來(lái)我們把2賦值給x插勤,x的名字只在該函數(shù)的內(nèi)部生效革骨。所以當(dāng)我們?cè)诤瘮?shù)里改變了x的值饮六,并不會(huì)對(duì)主代碼塊的x造成影響(名空間)苛蒲。
全局變量
如果你想定義一個(gè)全局變量绿满,你僅需要告知Python臂外,這個(gè)變量名不是局部的,是全局的喇颁,就可以了。我們將使用全局變量聲明橘霎。在函數(shù)里給函數(shù)外部的變量賦值,一定要使用全局變量聲明姐叁。
你可以在函數(shù)里使用函數(shù)外的變量瓦盛。然而這不是一個(gè)好的代碼習(xí)慣洗显,應(yīng)該避免這樣做原环,它會(huì)讓你的代碼不清晰,難以閱讀嘱吗,因?yàn)樽x者不知道變量定義在何處。全局變量的聲明就適用在這種情況谒麦。
例子(保存至function_global.py
):
x = 50
def func():
global x
print('x的值是:', x)
x = 2
print('變成了全局變量x:', x)
func()
print('外部x的值是:', x)
輸出:
$ python function_global.py
x的值是: 50
變成了全局變量x: 2
外部x的值是: 2
它是怎么運(yùn)作的呢?
全局變量聲明患膛,聲明x是一個(gè)全局變量迁匠,因此外部的x可以在函數(shù)里被賦值,當(dāng)然外部的x值也相應(yīng)的發(fā)生了改變城丧。
在一個(gè)全局變量聲明中,你可以指定多個(gè)全局變量亡哄。比如,global x, y, z愿卸。
默認(rèn)的參數(shù)值
一些函數(shù)截型,你可能想讓一些參數(shù)是可選的,也就是說(shuō)在調(diào)用的時(shí)候?qū)@些參數(shù)可以傳入?yún)?shù)值也可以不傳入?yún)?shù)值宦焦,當(dāng)不傳入?yún)?shù)值的時(shí)候,函數(shù)使用該參數(shù)的默認(rèn)值酝豪。參數(shù)的默認(rèn)值應(yīng)該在定義函數(shù)的時(shí)候定義精堕,也就是在參數(shù)后面添加操作符=和默認(rèn)值。
注意歹篓,參數(shù)的默認(rèn)值必須是一個(gè)常量揉阎,準(zhǔn)確說(shuō)痛悯,參數(shù)的默認(rèn)值是不能被修改的。下面的章節(jié)會(huì)對(duì)不能被修改的值做闡述≡孛龋現(xiàn)在,記住這點(diǎn)就可以了垮衷。
例子(保存至function_default.py
):
def say(message, times=1):
print(message*times)
say('你好')
say('驢子', 5)
輸出:
$ python function_default.py
你好
驢子驢子驢子驢子驢子
它是怎么運(yùn)作的呢乖坠?
函數(shù)say
用來(lái)打印字符串指定的次數(shù)。如果沒(méi)有提供打印的次數(shù)熊泵,會(huì)取默認(rèn)值也就是1, 那么將會(huì)打印字符串一次⌒煨恚可以看到,我們?cè)诙x函數(shù)的時(shí)候指定了打印次數(shù)的默認(rèn)值雌隅。
在第一次調(diào)用say
時(shí)缸沃,只傳入了一個(gè)字符串參數(shù),它把字符串打印了一次趾牧;第二次調(diào)用時(shí),傳入了字符串和次數(shù)梯皿,因此它把字符串打印了5次。
注意:
只有在參數(shù)列表最后端的參數(shù)能有默認(rèn)值县恕,也就是說(shuō)帶有默認(rèn)值的參數(shù)不能在沒(méi)有默認(rèn)值的參數(shù)前面剂桥,哈,有點(diǎn)拗口美尸。
這是因?yàn)閰?shù)依據(jù)參數(shù)列表的位置進(jìn)行賦值,比如說(shuō)师坎,def func(a, b=5)是一個(gè)有效的函數(shù),而def func(a=5, b)是一個(gè)非法的函數(shù)胯陋。
關(guān)鍵字參數(shù)
有些函數(shù)可能有很多參數(shù),并且你想通過(guò)指定名字來(lái)傳入?yún)?shù)值义矛,這種方式叫做關(guān)鍵字傳參盟萨。這種情況,我們使用關(guān)鍵字代替位置進(jìn)行傳參捻激。
這種傳參方式有兩個(gè)優(yōu)點(diǎn):
- 函數(shù)更容易使用:因?yàn)椴恍枰獡?dān)心忘記參數(shù)的順序。
- 我們可以只傳入我們想要傳入的參數(shù)胞谭。
例子(保存至function_keyword.py
):
def func(a, b=5, c=6):
print('a is %s, b is %s, c is %s' % (a, b, c))
func(3, 7)
func(3, c=25)
func(b=23, a=3)
輸出:
$ python function_keyword.py
a is 3, b is 7, c is 6
a is 3, b is 5, c is 25
a is 3, b is 23, c is 6
它是怎么運(yùn)作的呢韭赘?
函數(shù)func
有一個(gè)不帶默認(rèn)值的參數(shù),后面有兩個(gè)帶有默認(rèn)值的參數(shù)泉瞻。
第一次調(diào)用函數(shù),func(3, 7)侧巨,通過(guò)位置傳參,a被賦值3, b被賦值7, c取默認(rèn)值司忱。
第二次調(diào)用函數(shù)畴蹭,func(3, c=25), 通過(guò)關(guān)鍵字和位置傳參,a被賦值3, b取默認(rèn)值5, c被賦值25叨襟。
第三次調(diào)用函數(shù),func(b=23, a=3), 通過(guò)關(guān)鍵字傳參梳玫,a被賦值3, b被賦值23, c取默認(rèn)值6。
VarArgs參數(shù)
有時(shí)姚垃,你可能想要定義一個(gè)可以接收任意多個(gè)參數(shù)的函數(shù)盼忌,也就是接收個(gè)數(shù)可變的參數(shù)〔耆可以通過(guò)使用星號(hào)來(lái)達(dá)成服协。
例子(保存至function_varargs.py
):
def total(a=5, \*numbers, \*\*phonebook):
print('a', a)
for i in numbers:
print(i)
for key, value in phonebook.items():
print('關(guān)鍵字', key)
print('值', value)
print(total(10, 1, 2, 3, jack=1123, john=2231, inge=1560))
輸出:
a 10
1
2
3
關(guān)鍵字 jack
值 1123
關(guān)鍵字 john
值 2231
關(guān)鍵字 inge
值 1560
None
它是怎么運(yùn)作的呢窘游?
一個(gè)星號(hào)參數(shù)忍饰,表示所有位置參數(shù)值的集合。
雙星參數(shù)與它類(lèi)似斗塘,表示所有關(guān)鍵字參數(shù)值的集合馍盟。
return語(yǔ)句
return語(yǔ)句用來(lái)從函數(shù)返回贞岭,也就是瞄桨,跳出函數(shù),但是可以從函數(shù)返回一個(gè)值泊交。
例子(保存至function_return.py
):
def maxmum(x, y):
if x > y:
return x
elif x == y:
return '一樣大'
else:
return y
print(maxmum(2, 3))
輸出:
$ python function_return.py
3
它是怎么運(yùn)作的呢?
maxmum
函數(shù)返回參數(shù)中最大的數(shù),該函數(shù)用簡(jiǎn)單的if..else語(yǔ)句去找最大的數(shù)白指,然后返回這個(gè)數(shù)酵紫。
注意,一個(gè)不帶值的return語(yǔ)句等同于return None
奖地。None
是Python的一個(gè)特殊類(lèi)型,表示無(wú)仰楚。比如說(shuō)犬庇,可以用它來(lái)表示一個(gè)變量沒(méi)有值。
如果你沒(méi)有給函數(shù)寫(xiě)return語(yǔ)句捂襟,那么函數(shù)結(jié)尾處會(huì)隱式包含一個(gè)return None語(yǔ)句欢峰。some_function()
沒(méi)有寫(xiě)return語(yǔ)句,當(dāng)執(zhí)行print(some_function())
時(shí)纽帖,會(huì)打印一個(gè)None抛计。
def some_function():
pass
pass語(yǔ)句表示一個(gè)空的語(yǔ)句塊。
小提示:
內(nèi)置的max函數(shù)用來(lái)找最大數(shù)吹截,當(dāng)要找最大數(shù)時(shí),盡量用它晨逝。
文檔字符串
Python有個(gè)非常棒的特性懦铺,叫做文檔字符串。文檔字符串是一個(gè)重要的工具趁窃,它給程序做批注,讓程序更容易理解醒陆。更棒的是,我們還可以獲取到在執(zhí)行狀態(tài)的程序的文檔字符串寺晌。
例子(保存至function_docstrings.py
):
def print_max(x, y):
'''
打印兩個(gè)數(shù)中最大的數(shù)澡刹,這兩個(gè)數(shù)必須是整數(shù)。
'''
if x > y:
print(x, '是最大數(shù)')
else:
print(y, '是最大數(shù)')
print_max(3, 5)
print(print_max.__doc__)
輸出:
$ python function_docstrings.py
打印兩個(gè)數(shù)中最大的數(shù)陆赋,這兩個(gè)數(shù)必須是整數(shù)己莺。
它是怎么運(yùn)作的呢?
在函數(shù)體第一行的注釋內(nèi)容就是該函數(shù)的文檔字符串凌受。注意胜蛉,模塊和類(lèi)也有文檔字符串,在后面的內(nèi)容將會(huì)學(xué)到誊册。
文檔字符串,必須是多行字符串君旦。書(shū)寫(xiě)慣例:第一段簡(jiǎn)單介紹功能嘲碱,第二段是詳細(xì)的介紹,兩段間間隔一行恕稠。
如何獲取文檔字符串呢扶欣?在本例中千扶,print_max
函數(shù)通過(guò)它的屬性__doc__
來(lái)獲取文檔字符串骆捧。記住敛苇,Python所有都是對(duì)象接谨,當(dāng)然包括函數(shù)。
如果你用過(guò)help()
,你就會(huì)明白文檔字符串的作用驰徊。help
所作的就是獲取函數(shù)的doc屬性值颗味,然后把它漂亮的打印出來(lái)浦马。你可以試試它,在程序中加入代碼help(print_max.__doc__)
磺陡。記住币他,按q
鍵退出幫助窗口圆丹。
Python自動(dòng)從你的程序中收集文檔字符串硝枉。因此妻味,推薦你在寫(xiě)的有用函數(shù)加上文檔字符串责球。發(fā)布的Python項(xiàng)目有pydoc命令,它與使用help獲取文檔字符串類(lèi)似郑临。
總結(jié)
我們學(xué)習(xí)了函數(shù)的很多知識(shí)。但是依舊有些內(nèi)容沒(méi)有覆蓋到。
下一章節(jié),我們將學(xué)習(xí)使用踊淳、創(chuàng)建模塊陕靠。