當(dāng)我們使用Python編程時(shí),經(jīng)常會(huì)用到函數(shù)來實(shí)現(xiàn)一些特定的功能。Python可以使用def關(guān)鍵字定義一個(gè)函數(shù),并指定函數(shù)名和參數(shù)列表,函數(shù)體則是用來實(shí)現(xiàn)具體功能的部分。通過調(diào)用函數(shù),我們可以重復(fù)使用這段代碼,提高代碼的復(fù)用性和可維護(hù)性。
一、定義函數(shù)
定義函數(shù)使用關(guān)鍵字 def,后跟函數(shù)名與括號(hào)內(nèi)的形參列表。函數(shù)語(yǔ)句從下一行開始,并且必須縮進(jìn)。下列代碼創(chuàng)建一個(gè)可以輸出限定數(shù)值內(nèi)的斐波那契數(shù)列函數(shù):
>>>def fib(n): # write Fibonacci series up to n ... """Print a Fibonacci series up to n.""" ... a, b = 0, 1 ... while a < n: ... print(a, end=' ') ... a, b = b, a+b ... print() ... >>># Now call the function we just defined: ...fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
函數(shù)定義在當(dāng)前符號(hào)表中把函數(shù)名與函數(shù)對(duì)象關(guān)聯(lián)在一起。解釋器把函數(shù)名指向的對(duì)象作為用戶自定義函數(shù)。還可以使用其他名稱指向同一個(gè)函數(shù)對(duì)象,并訪問訪該函數(shù):
>>>fib <function fib at 10042ed0> >>>f = fib >>>f(100) 0 1 1 2 3 5 8 13 21 34 55 89
fib 不返回值,因此,其他語(yǔ)言不把它當(dāng)作函數(shù),而是當(dāng)作過程。事實(shí)上,沒有 return 語(yǔ)句的函數(shù)也返回值,只不過這個(gè)值比較是 None (是一個(gè)內(nèi)置名稱)。一般來說,解釋器不會(huì)輸出單獨(dú)的返回值 None ,如需查看該值,可以使用 print():
>>>fib(0) >>>print(fib(0)) None
編寫不直接輸出斐波那契數(shù)列運(yùn)算結(jié)果,而是返回運(yùn)算結(jié)果列表的函數(shù)也非常簡(jiǎn)單:
>>>def fib2(n): # return Fibonacci series up to n ... """Return a list containing the Fibonacci series up to n.""" ... result = [] ... a, b = 0, 1 ... while a < n: ... result.append(a) # see below ... a, b = b, a+b ... return result ... >>>f100 = fib2(100) # call it >>>f100 # write the result [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
本例也新引入了一些 Python 功能:
- return 語(yǔ)句返回函數(shù)的值。return 語(yǔ)句不帶表達(dá)式參數(shù)時(shí),返回 None。函數(shù)執(zhí)行完畢退出也返回 None。
- 語(yǔ)句 result.append(a) 調(diào)用了列表對(duì)象 result 的 方法。 方法是‘從屬于’對(duì)象的函數(shù),其名稱為 obj.methodname,其中 obj 是某個(gè)對(duì)象(可以是一個(gè)表達(dá)式),methodname 是由對(duì)象的類型定義的方法名稱。 不同的類型定義了不同的方法。 不同的類型的方法可以使用相同的名稱而不會(huì)產(chǎn)生歧義。 (使用 類 可以定義自己的對(duì)象類型和方法,參見 類。) 在示例中顯示的方法 append() 是由列表對(duì)象定義的;它會(huì)在列表的末尾添加一個(gè)新元素。 在本例中它等同于 result = result + [a],但效率更高。
二、默認(rèn)值參數(shù)
為參數(shù)指定默認(rèn)值是非常有用的方式。調(diào)用函數(shù)時(shí),可以使用比定義時(shí)更少的參數(shù),例如:
def ask_ok(prompt, retries=4, reminder='Please try again!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise ValueError('invalid user response') print(reminder)
該函數(shù)可以用以下方式調(diào)用:
- 只給出必選實(shí)參:ask_ok(‘Do you really want to quit?’)
- 給出一個(gè)可選實(shí)參:ask_ok(‘OK to overwrite the file?’, 2)
- 給出所有實(shí)參:ask_ok(‘OK to overwrite the file?’, 2, ‘Come on, only yes or no!’)
本例還使用了關(guān)鍵字 in ,用于確認(rèn)序列中是否包含某個(gè)值。
默認(rèn)值在 定義 作用域里的函數(shù)定義中求值,所以:
i = 5 def f(arg=i): print(arg) i = 6 f()
上例輸出的是 5。
注意:默認(rèn)值只計(jì)算一次。默認(rèn)值為列表、字典或類實(shí)例等可變對(duì)象時(shí),會(huì)產(chǎn)生與該規(guī)則不同的結(jié)果。例如,下面的函數(shù)會(huì)累積后續(xù)調(diào)用時(shí)傳遞的參數(shù):
def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3))
輸出結(jié)果如下:
[1] [1, 2] [1, 2, 3]
不想在后續(xù)調(diào)用之間共享默認(rèn)值時(shí),應(yīng)以如下方式編寫函數(shù):
def f(a, L=None): if L is None: L = [] L.append(a) return L
三、關(guān)鍵字參數(shù)
函數(shù)也可以使用 kwarg = value 的關(guān)鍵字參數(shù)形式被調(diào)用。例如,以下函數(shù):
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!")
該函數(shù)接受一個(gè)必選參數(shù)(voltage)和三個(gè)可選參數(shù)(state, action 和 type)。該函數(shù)可用下列方式調(diào)用:
parrot(1000) # 1 positional argument parrot(voltage=1000) # 1 keyword argument parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments parrot('a million', 'bereft of life', 'jump') # 3 positional arguments parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
以下為錯(cuò)誤調(diào)用方法:
parrot() # required argument missing parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument parrot(110, voltage=220) # duplicate value for the same argument parrot(actor='John Cleese') # unknown keyword argument
四、返回值
Python 函數(shù)使用 return 語(yǔ)句返回函數(shù)值,可以將函數(shù)作為一個(gè)值賦值給指定變量:
def return_sum(x,y): c = x + y return c res = return_sum(4,5) print(res)
也可以讓函數(shù)返回空值:
def empty_return(x,y): c = x + y return res = empty_return(4,5) print(res)
五、可變參數(shù)列表
最后,一個(gè)較不常用的功能是可以讓函數(shù)調(diào)用可變個(gè)數(shù)的參數(shù)。這些參數(shù)被包裝進(jìn)一個(gè)元組(查看元組和序列)。在這些可變個(gè)數(shù)的參數(shù)之前,可以有零到多個(gè)普通的參數(shù):
def arithmetic_mean(*args): if len(args) == 0: return 0 else: sum = 0 for x in args: sum += x return sum/len(args) print(arithmetic_mean(45,32,89,78)) print(arithmetic_mean(8989.8,78787.78,3453,78778.73)) print(arithmetic_mean(45,32)) print(arithmetic_mean(45)) print(arithmetic_mean())
以上實(shí)例輸出結(jié)果為:
61.0 42502.3275 38.5 45.0 0