函數(shù)


函數(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ù)ab。我們用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):

  1. 函數(shù)更容易使用:因?yàn)椴恍枰獡?dān)心忘記參數(shù)的順序。
  2. 我們可以只傳入我們想要傳入的參數(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)建模塊陕靠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市说榆,隨后出現(xiàn)的幾起案子签财,更是在濱河造成了極大的恐慌唱蒸,老刑警劉巖庆捺,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡坏匪,警方通過(guò)查閱死者的電腦和手機(jī)剥槐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)几于,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沿彭,“玉大人,你說(shuō)我怎么就攤上這事睦裳。” “怎么了倒谷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵抖格,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我捡需,道長(zhǎng),這世上最難降的妖魔是什么饰剥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任棒卷,我火速辦了婚禮若厚,結(jié)果婚禮上蜒什,老公的妹妹穿的比我還像新娘霎冯。我一直安慰自己沈撞,他們只是感情好关串,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布墓卦。 她就那樣靜靜地躺著落剪,像睡著了一般忠怖。 火紅的嫁衣襯著肌膚如雪枉疼。 梳的紋絲不亂的頭發(fā)上骂维,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音潦刃,去河邊找鬼。 笑死笆包,一個(gè)胖子當(dāng)著我的面吹牛庵佣,可吹牛的內(nèi)容都是我干的巴粪。 我是一名探鬼主播辫塌,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼储矩!你這毒婦竟也來(lái)了即硼?” 一聲冷哼從身側(cè)響起只酥,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赠潦,失蹤者是張志新(化名)和其女友劉穎瓮增,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凡资,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片田绑。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昙篙,靈堂內(nèi)的尸體忽然破棺而出缴挖,到底是詐尸還是另有隱情焚辅,我是刑警寧澤棚点,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布默责,位于F島的核電站,受9級(jí)特大地震影響桃序,放射性物質(zhì)發(fā)生泄漏奇适。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一注竿、第九天 我趴在偏房一處隱蔽的房頂上張望巩割。 院中可真熱鬧宣谈,春花似錦、人聲如沸漩怎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叁执。三九已至,卻和暖如春次哈,著一層夾襖步出監(jiān)牢的瞬間吆录,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工葛假, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滋恬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓带斑,卻偏偏與公主長(zhǎng)得像勋拟,于是被迫代替她去往敵國(guó)和親敢靡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纺念,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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