閱讀目錄
一 數學定義的函數與python中的函數
二 爲何使用函數
背景提要
三 函數和過程
四 函數參數
五 局部變量和全局變量
六 前向引用之'函數即變量'
七 嵌套函數和作用域
八 遞歸
九 匿名函數
十 函數式編程
十一 內置函數
十二 本節作業
一 數學定義的函數與python中的函數
初中數學函數定義:一般的,在一個變化過程中,如果有兩個變量x和y,並且對於x的每一個確定的值,y都有唯一確定的值與其對應,那麼我們就把x稱爲自變量,把y稱爲因變量,y是x的函數。自變量x的取值範圍叫做這個函數的定義域
例如y=2*x
python中函數定義:函數是邏輯結構化和過程化的一種編程方法。
1 python中函數定義方法:
2
3 def test(x):
4 "The function definitions"
5 x+=1
6 return x
7
8 def:定義函數的關鍵字
9 test:函數名
10 ():內可定義形參
11 "":文檔描述(非必要,但是強烈建議爲你的函數添加描述信息)
12 x+=1:泛指代碼塊或程序處理邏輯
13 return:定義返回值
調用運行:可以帶參數也可以不帶
函數名()
補充:
1.編程語言中的函數與數學意義的函數是截然不同的倆個概念,編程語言中的函數是通過一個函數名封裝好一串用來完成某一特定功能的邏輯,數學定義的函數就是一個等式,等式在傳入因變量值x不同會得到一個結果y,這一點與編程語言中類似(也是傳入一個參數,得到一個返回值),不同的是數學意義的函數,傳入值相同,得到的結果必然相同且沒有任何變量的修改(不修改狀態),而編程語言中的函數傳入的參數相同返回值可不一定相同且可以修改其他的全局變量值(因爲一個函數a的執行可能依賴於另外一個函數b的結果,b可能得到不同結果,那即便是你給a傳入相同的參數,那麼a得到的結果也肯定不同)
2.函數式編程就是:先定義一個數學函數(數學建模),然後按照這個數學模型用編程語言去實現它。至於具體如何實現和這麼做的好處,且看後續的函數式編程。
二 爲何使用函數
背景提要
現在老闆讓你寫一個監控程序,監控服務器的系統狀況,當cpu\memory\disk等指標的使用量超過閥值時即發郵件報警,你掏空了所有的知識量,寫出了以下代碼
1 while True:
2 if cpu利用率 > 90%:
3 #發送郵件提醒
4 連接郵箱服務器
5 發送郵件
6 關閉連接
7
8 if 硬盤使用空間 > 90%:
9 #發送郵件提醒
10 連接郵箱服務器
11 發送郵件
12 關閉連接
13
14 if 內存佔用 > 80%:
15 #發送郵件提醒
16 連接郵箱服務器
17 發送郵件
18 關閉連接
def 發送郵件(內容)
#發送郵件提醒
連接郵箱服務器
發送郵件
關閉連接
while True:
if cpu利用率 > 90%:
發送郵件('CPU報警')
if 硬盤使用空間 > 90%:
發送郵件('硬盤報警')
if 內存佔用 > 80%:
發送郵件('內存報警')
總結使用函數的好處:
1.代碼重用
2.保持一致性,易維護
3.可擴展性
三 函數和過程
過程定義:過程就是簡單特殊沒有返回值的函數
這麼看來我們在討論爲何使用函數的的時候引入的函數,都沒有返回值,沒有返回值就是過程,沒錯,但是在python中有比較神奇的事情
1 def test01():
2 msg='hello The little green frog'
3 print msg
4
5 def test02():
6 msg='hello WuDaLang'
7 print msg
8 return msg
9
10
11 t1=test01()
12
13 t2=test02()
14
15
16 print 'from test01 return is [%s]' %t1
17 print 'from test02 return is [%s]' %t2
總結:當一個函數/過程沒有使用return顯示的定義返回值時,python解釋器會隱式的返回None,
所以在python中即便是過程也可以算作函數。
1 def test01():
2 pass
3
4 def test02():
5 return 0
6
7 def test03():
8 return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'}
9
10 t1=test01()
11 t2=test02()
12 t3=test03()
13
14
15 print 'from test01 return is [%s]: ' %type(t1),t1
16 print 'from test02 return is [%s]: ' %type(t2),t2
17 print 'from test03 return is [%s]: ' %type(t3),t3
總結:
返回值數=0:返回None
返回值數=1:返回object
返回值數>1:返回tuple
四 函數參數
1.形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量
2.實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值
3.位置參數和關鍵字(標準調用:實參與形參位置一一對應;關鍵字調用:位置無需固定)
4.默認參數
5.參數組
五 局部變量和全局變量
在子程序中定義的變量稱爲局部變量,在程序的一開始定義的變量稱爲全局變量。
全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。
當全局變量與局部變量同名時:
在定義局部變量的子程序內,局部變量起作用;在其它地方全局變量起作用。
1 name='lhf'
2
3 def change_name():
4 print('我的名字',name)
5
6 change_name()
7
8
9 def change_name():
10 name='帥了一筆'
11 print('我的名字',name)
12
13 change_name()
14 print(name)
15
16
17
18 def change_name():
19 global name
20 name='帥了一筆'
21 print('我的名字',name)
22
23 change_name()
24 print(name)
六 前向引用之'函數即變量'
1 def action():
2 print 'in the action'
3 logger()
4 action()
5 報錯NameError: global name 'logger' is not defined
6
7
8 def logger():
9 print 'in the logger'
10 def action():
11 print 'in the action'
12 logger()
13
14 action()
15
16
17 def action():
18 print 'in the action'
19 logger()
20 def logger():
21 print 'in the logger'
22
23 action()
七 嵌套函數和作用域
看上面的標題的意思是,函數還能套函數?of course
1 name = "Alex"
2
3 def change_name():
4 name = "Alex2"
5
6 def change_name2():
7 name = "Alex3"
8 print("第3層打印",name)
9
10 change_name2() #調用內層函數
11 print("第2層打印",name)
12
13
14 change_name()
15 print("最外層打印",name)
此時,在最外層調用change_name2()會出現什麼效果?
沒錯, 出錯了, 爲什麼呢?
作用域在定義函數時就已經固定住了,不會隨着調用位置的改變而改變
1 例一:
2 name='alex'
3
4 def foo():
5 name='lhf'
6 def bar():
7 print(name)
8 return bar
9
10 func=foo()
11 func()
12
13
14 例二:
15 name='alex'
16
17 def foo():
18 name='lhf'
19 def bar():
20 name='wupeiqi'
21 def tt():
22 print(name)
23 return tt
24 return bar
25
26 func=foo()
27 func()()
八 遞歸
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
1 def calc(n):
2 print(n)
3 if int(n/2) ==0:
4 return n
5 return calc(int(n/2))
6
7 calc(10)
8
9 輸出:
10 10
11 5
12 2
13 1
遞歸問路
遞歸特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)
堆棧掃盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
二分查找
九 匿名函數
匿名函數就是不需要顯式的指定函數
1 #這段代碼
2 def calc(n):
3 return n**n
4 print(calc(10))
5
6 #換成匿名函數
7 calc = lambda n:n**n
8 print(calc(10))
1 l=[3,2,100,999,213,1111,31121,333]
2 print(max(l))
3
4 dic={'k1':10,'k2':100,'k3':30}
5
6
7 print(max(dic))
8 print(dic[max(dic,key=lambda k:dic[k])])
1 res = map(lambda x:x**2,[1,5,7,4,8])
2 for i in res:
3 print(i)
4
5 輸出
6 1
7 25
8 49
9 16
10 64
十 函數式編程
11 高階函數
滿足倆個特性任意一個即爲高階函數
1.函數的傳入參數是一個函數名
2.函數的返回值是一個函數名
map函數
reduce函數
filter函數
總結
十一 內置函數
View Code
內置參數詳解 https://docs.python.org/3/library/functions.html?highlight=built#ascii