標籤:變化 class 輸入 數組 sel 是你 2016年 釋放 串連
閱讀目錄
- 一 數學定義的函數與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 關閉串連
上面的代碼實現了功能,但即使是鄰居老王也看出了端倪,老王親切的摸了下你家兒子的臉蛋,說,你這個重複代碼太多了,每次警示都要重寫一段發郵件的代碼,太low了,這樣幹存在2個問題:
- 代碼重複過多,一個勁的copy and paste不符合高端程式員的氣質
- 如果日後需要修改發郵件的這段代碼,比如加入群發功能,那你就需要在所有用到這段代碼的地方都修改一遍
你覺得老王說的對,你也不想寫重複代碼,但又不知道怎麼搞,老王好像看出了你的心思,此時他抱起你兒子,笑著說,其實很簡單,只需要把重複的代碼提取出來,放在一個公用的地方,起個名字,以後誰想用這段代碼,就通過這個名字調用就行了,如下
def 發送郵件(內容) #發送寄件提醒 串連郵箱伺服器 發送郵件 關閉串連 while True: if cpu利用率 > 90%: 發送郵件(‘CPU警示‘) if 硬碟使用空間 > 90%: 發送郵件(‘硬碟警示‘) if 記憶體佔用 > 80%: 發送郵件(‘記憶體警示‘)
你看著老王寫的代碼,氣勢恢宏、磅礴大氣,代碼裡透露著一股內斂的傲氣,心想,老王這個人真是不一般,突然對他的背景更感興趣了,問老王,這些花式玩法你都是怎麼知道的? 老王親了一口你兒子,捋了捋不存在的鬍子,淡淡的講,“老夫,年少時,師從京西沙河淫魔銀角大王 ”, 你一聽“銀角大王”這幾個字,不由的嬌軀一震,心想,真nb,怪不得代碼寫的這麼6, 這“銀角大王”當年在江湖上可是數得著的響噹噹的名字,只可惜後期縱慾過度,卒於公元2016年, 真是可惜了,只留下其哥哥孤守當年兄弟倆一起打下來的江山。 此時你看著的老王離開的身影,感覺你兒子跟他越來越像了。。。
總結使用函數的好處:
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]‘ %t117 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),t116 print ‘from test02 return is [%s]: ‘ %type(t2),t217 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 name20 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 tt24 return bar25 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 1011 512 213 1
遞迴特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少
3. 遞迴效率不高,遞迴層次過多會導致棧溢出(在電腦中,函數調用是通過棧(stack)這種資料結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴調用的次數過多,會導致棧溢出)
堆棧掃盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
尾遞迴最佳化:http://egon09.blog.51cto.com/9161406/1842475
九 匿名函數
匿名函數就是不需要顯式的指定函數
1 #這段代碼2 def calc(n):3 return n**n4 print(calc(10))5 6 #換成匿名函數7 calc = lambda n:n**n8 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 1610 64
十 函數式編程
峰哥原創面向過程解釋:
函數的參數傳入,是函數吃進去的食物,而函數return的傳回值,是函數拉出來的結果,面向過程的思路就是,把程式的執行當做一串首尾相連的函數,一個函數吃,拉出的東西給另外一個函數吃,另外一個函數吃了再繼續拉給下一個函數吃。。。
例如:
使用者登入流程:前端接收處理使用者請求-》將使用者資訊傳給邏輯層,邏輯詞處理使用者資訊-》將使用者資訊寫入資料庫
驗證使用者登入流程:資料庫查詢/處理使用者資訊-》交給邏輯層,邏輯層處理使用者資訊-》使用者資訊交給前端,最上層顯示使用者資訊
函數式編程:
http://egon09.blog.51cto.com/9161406/1842475
11 高階函數
滿足倆個特性任意一個即為高階函數
1.函數的傳入參數是一個函數名
2.函數的傳回值是一個函數名
十一 內建函數
內建參數詳解 https://docs.python.org/3/library/functions.html?highlight=built#ascii
十二 本節作業
有以下員工資訊表
當然此表你在檔案儲存體時可以這樣表示
1 1,Alex Li,22,13651054608,IT,2013-04-01
現需要對這個員工資訊檔,實現增刪改查操作
- 可進行模糊查詢,文法至少支援下面3種:
- select name,age from staff_table where age > 22
- select * from staff_table where dept = "IT"
- select * from staff_table where enroll_date like "2013"
- 查到的資訊,列印後,最後面還要顯示查到的條數
- 可建立新員工紀錄,以phone做唯一鍵,staff_id需自增
- 可刪除指定員工資訊紀錄,輸入員工id,即可刪除
- 可修改員工資訊,文法如下:
- UPDATE staff_table SET dept="Market" WHERE where dept = "IT"
注意:以上需求,要充分使用函數,請盡你的最大限度來減少重複代碼!
第七篇 python基礎之函數,遞迴,內建函數