無參定義函數(shù)
1. 語法
def function_name():
expressions
Python 使用def
開始函數(shù)定義,緊接著是函數(shù)名屑那,括號內(nèi)部為函數(shù)的參數(shù)落恼,內(nèi)部為函數(shù)的 具體功能實(shí)現(xiàn)代碼关霸,如果想要函數(shù)有返回值, 在 expressions
中的邏輯代碼中用return
返回。
2. 實(shí)例
def function():
print('This is a function')
a = 1+2
print(a)
上面我們定義了一個名字為function
的函數(shù)荚板,函數(shù)沒有接收參數(shù)凤壁,所以括號內(nèi)部為空,緊接著就是 函數(shù)的功能代碼跪另。如果執(zhí)行該腳本拧抖,發(fā)現(xiàn)并沒有輸出任何輸出,因?yàn)槲覀冎欢x了函數(shù)免绿,而并沒有執(zhí)行函數(shù)唧席。 這時我們在 Python 命令提示符中輸入函數(shù)調(diào)用 function()
, 注意這里調(diào)用函數(shù)的括號不能省略。那么 函數(shù)內(nèi)部的功能代碼將會執(zhí)行嘲驾,輸出結(jié)果:
This is a function
3
帶參定義函數(shù)
1. 語法
def function_name(parameters):
expressions
2. 實(shí)例
def func(a, b):
c = a+b
print('the c is ', c)
在這里定義的一個函數(shù)淌哟,其參數(shù)就是兩個數(shù)值,函數(shù)的功能就是把兩個參數(shù)加起來辽故。運(yùn)行腳本后徒仓,在 Python 提示符內(nèi)調(diào)用函數(shù) func
, 如果不指定參數(shù) func()
, 那么將會出錯; 輸出 func(1, 2)
,將 a=1
, b=2
傳入函數(shù)誊垢,輸出 the c is 3
掉弛。所以在調(diào)用函數(shù)時候,參數(shù)個數(shù)和位置一定要按照函數(shù)定義喂走。如果我們忘記了函數(shù)的參數(shù)的位置殃饿,只知道各個參數(shù)的名字,可以在 函數(shù)調(diào)用的過程中給指明特定的參數(shù) func(a=1, b=2)
, 這樣的話芋肠,參數(shù)的位置將不受影響壁晒,所以 func(b=2,a=1)
是同樣的 的效果。
函數(shù)默認(rèn)參數(shù)
1. 語法
def function_name(para_1,...,para_n=defau_n,..., para_m=defau_m):
expressions
函數(shù)聲明只需要在需要默認(rèn)參數(shù)的地方用=
號給定即可, 但是要注意所有的默認(rèn)參數(shù)都不能出現(xiàn)在非默認(rèn)參數(shù)的前面。
2. 實(shí)例
def sale_car(price, color='red', brand='carmy', is_second_hand=True):
print('price', price,
'color', color,
'brand', brand,
'is_second_hand', is_second_hand,)
在這里定義了一個 sale_car
函數(shù)秒咐,參數(shù)為車的屬性谬晕,但除了 price 之外,像 color
, brand
和 is_second_hand
都是有默認(rèn)值的携取,如果我們調(diào)用函數(shù) sale_car(1000)
, 那么與 sale_car(1000, 'red', 'carmy', True)
是一樣的效果攒钳。當(dāng)然也可以在函數(shù)調(diào)用過程中傳入特定的參數(shù)用來修改默認(rèn)參數(shù)。通過默認(rèn)參數(shù)可以減輕我們函數(shù)調(diào)用的復(fù)雜度雷滋。
注意:默認(rèn)值放在非默認(rèn)值之后
3. 進(jìn)階
-
3.1 自調(diào)用
如果想要在執(zhí)行腳本的時候執(zhí)行一些代碼不撑,比如單元測試,可以在腳本最后加上單元測試 代碼晤斩,但是該腳本作為一個模塊對外提供功能的時候單元測試代碼也會執(zhí)行焕檬,這些往往我們不想要的,我們可以把這些代碼放入腳本最后:
if __name__ == '__main__':
#code_here
如果執(zhí)行該腳本的時候澳泵,該if
判斷語句將會是 True
,那么內(nèi)部的代碼將會執(zhí)行实愚。 如果外部調(diào)用該腳本,if
判斷語句則為False
,內(nèi)部代碼將不會執(zhí)行兔辅。
單元測試舉例
①首先定義了一個測試函數(shù):namefunction.py
def get_formmed_name(first, last):
"""該函數(shù)根據(jù)姓和名生成一個完整的姓名"""
full_name = first + ' ' + last
return full_name.title()
②然后編寫了一個測試該函數(shù)的模塊:names.py
from name_function import get_formmed_name
"""該文件用來測試姓名生成函數(shù)"""
print "Enter 'q' to quit any time."
while True:
first = raw_input("\nEnter first name:")
if first == 'q':
break
last = raw_input("Enter last name:")
if last == 'q':
break
formatted_name = get_formmed_name(first,last)
print "Formmated name:",formatted_name
通過測試腊敲,name_function中的函數(shù)可以實(shí)現(xiàn)其功能。
③最后是單元測試和測試用例的編寫维苔。 test_name_function.py
import unittest
from name_function import get_formmed_name
class NamesTestCase(unittest.TestCase):
"""測試name_function.py"""
def test_first_last_name(self):
"""能夠正確處理像Janis Joplin這樣的姓名嗎碰辅?"""
formatted_name = get_formmed_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
#注意這個地方,我在Python 2.7的版本中直接調(diào)用書上的主函數(shù)
#unittest.main()時程序無法通過介时,而改用以下調(diào)用方式即可
if __name__ == '__main__':
unittest
通過對以上單元測試模塊分析:
- 導(dǎo)入單元測試類
unittest
- 導(dǎo)入要測試的函數(shù)没宾,本例為
name_function
模塊中的get_formatted_name()
函數(shù) - 創(chuàng)建一個繼承于
unittest.TestCase
的類 - 在類中定義一系列方法對函數(shù)的行為進(jìn)行不同方面的測試,需要注意的是一個測試用例應(yīng)該只測試一個方面沸柔,測試目的和測試內(nèi)容應(yīng)很明確榕吼。主要是調(diào)用
assertEqual
、assertRaises
等斷言方法判斷程序執(zhí)行結(jié)果和預(yù)期值是否相符勉失。
-
3.2 可變參數(shù)
顧名思義羹蚣,函數(shù)的可變參數(shù)是傳入的參數(shù)可以變化的,1個乱凿,2個到任意個顽素。當(dāng)然可以將這些 參數(shù)封裝成一個list
或者 tuple
傳入,但不夠 pythonic
徒蟆。使用可變參數(shù)可以很好解決該問題胁出,注意可變參數(shù)在函數(shù)定義不能出現(xiàn)在特定參數(shù)和默認(rèn)參數(shù)前面,因?yàn)榭勺儏?shù)會吞噬掉這些參數(shù)段审。
def report(name, *grades):
total_grade = 0
for grade in grades:
total_grade += grade
print(name, 'total grade is ', total_grade)
定義了一個函數(shù)全蝶,傳入一個參數(shù)為name
, 后面的參數(shù)*grades
使用了*
修飾,表明該參數(shù)是一個可變參數(shù),這是一個可迭代的對象抑淫。該函數(shù)輸入姓名和各科的成績绷落,輸出姓名和總共成績。所以可以這樣調(diào)用函數(shù) report('Mike', 8, 9)
始苇,輸出的結(jié)果為 Mike total grade is 17
, 也可以這樣調(diào)用 report('Mike', 8, 9, 10)
砌烁,輸出的結(jié)果為 Mike total grade is 27
-
3.3 關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)可以傳入0個或者任意個含參數(shù)名的參數(shù),這些參數(shù)名在函數(shù)定義中并沒有出現(xiàn)催式,這些參數(shù)在函數(shù)內(nèi)部自動封裝成一個字典(dict).
def portrait(name, **kw):
print('name is', name)
for k,v in kw.items():
print(k, v)
定義了一個函數(shù)函喉,傳入一個參數(shù) name
, 和關(guān)鍵字參數(shù) kw
,使用了**
修飾荣月。表明該參數(shù)是關(guān)鍵字參數(shù)管呵,通常來講關(guān)鍵字參數(shù)是放在函數(shù)參數(shù)列表的最后。如果調(diào)用參數(shù) portrait('Mike', age=24, country='China', education='bachelor')
輸出:
name is Mike
age 24
country China
education bachelor
通過可變參數(shù)和關(guān)鍵字參數(shù)哺窄,任何函數(shù)都可以用 universal_func(*args, **kw) 表達(dá)捐下。
全局變量、局部變量
-
局部變量
在 def
中, 我們可以定義一個局部變量, 這個變量 a
只能在這個功能 fun
中有效, 出了這個功能, a
這個變量就不是那個局部的 a
.
def fun():
a = 10
print(a)
return a+100
print(fun())
"""
10
110
"""
下面這個例子就驗(yàn)證了如果在 fun
外面調(diào)用a
, 會報錯, 這表明外面的這個 print(a)
不能找到那個局部的 a
, 只有全局變量再能在外面被調(diào)用, 比如 APPLE
.
APPLY = 100 # 全局變量
def fun():
a = 10 # 局部變量
return a+100
print(APPLE) # 100
print(a) # 報錯, 不能拿到一個局部變量的值
-
全局變量
首先我們在外部定義一個全局變量 a=None
, 然后再 fun()
中聲明 這個a
是來自外部的 a
. 聲明方式就是 global a
APPLY = 100 # 全局變量
a = None
def fun():
global a # 使用之前在全局里定義的 a
a = 20 # 現(xiàn)在的 a 是全局變量了
return a+100
print(APPLE) # 100
print('a past:', a) # None
fun()
print('a now:', a) # 20