0x01 什麼是函數
函數就是一段代碼裡面可重複使用的部分,我們在寫程式的時候常常都會遇到一些需要重用的功能,若將其功能寫成一個函數,那我們就不必要寫多一次該代碼,只需直接套用該函數就可以了。
0x02 函數的定義規則
- 以def關鍵字眼為開頭,後面接的是你要定義的函數名稱和圓括號()。
- 任何在這函數裡面會出現的參數和自變量需放在圓括號裡面,因為裡面是讓你來定義參數的。
- 函數第一行可以選擇性使用文檔字符串對所存放的函數加以說明。
- 函數內容會以冒號:開始並且在下一行後開始縮進。
- return [表達式] 代表你會結束該函數,選擇性地返回一個數值給調用方,若沒有表達式return就是說你返回的是None。
格式
1 | def 函數名(参數列表): |
0x03 例子
比如說我們要生成一個有指定邊界的斐波那契數列的函數:
1 | >>> def fib(n): # write Fibonacci series up to n |
在上述的函數裡面,所有變量的賦值會存在局部符號表(Local Symbol Table)裡面。變量引用會先檢查局部符號表,接著就是包含函數的局部符號表,跟在後面是全局符號表,最後則是內置名字表。因此,全局變量是不能直接在函數裡面賦值(要用global語句來命名)。
一個函數定義會在當前的符號表裡面引入函數名字。而函數名字的值(函數體)會被Python的解釋器認為是用戶自定義的類型,之後可賦予其他的名字(變量名字以及被當作其他函數來使用。
比如說這樣:
1 | >>> fib |
0x04 深入了解如何定義函數
現在我們就可以開始深入了解3種形式的函數使用方式。方式有這3種類型:
- 默認參數
- 關鍵字參數
- 可變參數列表
- Lambda形式
默認參數
在Python裡面最常見的默認函數的形式多數含有一個或多個的實際參數,這使到該函數在被呼叫的時候可以使用更少已被定義的實際函數。我們來看看下面的例子:1
2
3
4
5
6
7
8
9
10
11def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
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 OSError('uncooperative user')
print(complaint)
此函數的調用方式:
- 只給出必要的参數
ask_ok('Do you really want to quit?')
- 給出一個可選的参數
ask_ok('OK to overwrite the file?', 2)
- 給出所有的參數
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
調用函數的時候,如果沒有傳遞參數,也會使用默認的參數。以下是沒有傳入參數的實際例子。1
2
3
4
5
6def printinfo(name,age = 24):
print("Name: ", name)
print("Age: ", age)
return
printinfo(age = 10,name="Bean Bean")
關鍵字參數
也可以把函數裡面的參數設定成某個固定的關鍵字來進行調用(Keyword = Value)。
例子:1
2
3
4
5def 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, "!")
在這例子裡面,可以接受一個必選參數 (voltage) 以及三個可選參數 (state, action, 和 type)。可以用以下任何一個方法來進行調用:1
2
3
4
5
6parrot(5000) # 1 positional argument
parrot(voltage=5000) # 1 keyword argument
parrot(voltage=5000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=5000000) # 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
那麼無效的調用例子又是怎樣的呢?1
2
3
4parrot() # 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
另外,關鍵字的參數也必須跟隨在位置參數的後面。在傳遞期間,所有的關鍵字參數必須與函數可接受的某個參數互相匹配。而且任何参数都不可以多次赋值。下面的示例由于這種限制而無法呼叫該函數:
1 | >>> def function(a): |
在函數調用期間,關鍵字函數可以被使用來確定傳入的參數值。另外調用時候參數的順序與聲明時不一致也沒關係,因為Python解釋器會自動匹配相關參數值。
來看下這個程式:1
2
3
4
5
6
7
8
9
10
11#可以解釋函數
def printme(str):
"Print any entered String"
print (str);
return;
#调用printme函數
printme(str = "Pikachu is cute!");
結果
Pikachu is cute!
暫時沒用
在你引入一個像**name
的參數時候,它會接收一個字典 Maping Types - dict。該字典包含了所有未出現在形式參數列表中的關鍵字參數。著
该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如 name (下一小节详细介绍) 的形式参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值( name 必须在 **name 之前出现)。 例如,我们这样定义一个函数:
1 | def cheeseshop(kind, *arguments, **keywords): |
可變參數列表
讓函數調用可變個數的參數。這些參數會被包裝進一個元組。
1 | def write_multiple_items(file, separator, *args): |
lambda 函數
【暫時沒有用到】
- 參數列表的分析
- 函數註解
參考網站
http://www.runoob.com/python3/python3-function.html
http://docs.pythontab.com/python/python3.4/controlflow.html#tut-functions