python中的函數


---恢復內容開始---

一 數學定義的函數與python中的函數

初中數學函數定義:一般的,在一個變化過程中,如果有兩個變量x和y,並且對於x的每一個確定的值,y都有唯一確定的值與其對應,那么我們就把x稱為自變量,把y稱為因變量,y是x的函數。自變量x的取值范圍叫做這個函數的定義域

例如y=2*x

python中函數定義:函數是邏輯結構化和過程化的一種編程方法。

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等指標的使用量超過閥值時即發郵件報警,你掏空了所有的知識量,寫出了以下代碼

 

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         關閉連接

三 函數和過程

過程定義:過程就是簡單特殊沒有返回值的函數

這么看來我們在討論為何使用函數的的時候引入的函數,都沒有返回值,沒有返回值就是過程,沒錯,但是在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中即便是過程也可以算作函數。

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.參數組

五 局部變量和全局變量

在子程序中定義的變量稱為局部變量,在程序的一開始定義的變量稱為全局變量。
全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。
當全局變量與局部變量同名時:
在定義局部變量的子程序內,局部變量起作用;在其它地方全局變量起作用。
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)

六 前向引用之'函數即變量'

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()()

八 遞歸

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

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
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import time

person_list=['alex','wupeiqi','yuanhao','linhaifeng']
def ask_way(person_list):
    print('-'*60)
    if len(person_list) == 0:
        return '沒人知道'
    person=person_list.pop(0)
    if person == 'linhaifeng':
        return '%s說:我知道,老男孩就在沙河匯德商廈,下地鐵就是' %person
    print('hi 美男[%s],敢問路在何方' %person)
    print('%s回答道:我不知道,但念你慧眼識豬,你等着,我幫你問問%s...' %(person,person_list))
    time.sleep(3)
    res=ask_way(person_list)
    # print('%s問的結果是: %res' %(person,res))
    return res



res=ask_way(person_list)

print(res)

遞歸特性:

1. 必須有一個明確的結束條件

2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少

3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)

堆棧掃盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html 

尾遞歸優化:http://egon09.blog.51cto.com/9161406/1842475

data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
 
 
def binary_search(dataset,find_num):
    print(dataset)
 
    if len(dataset) >1:
        mid = int(len(dataset)/2)
        if dataset[mid] == find_num:  #find it
            print("找到數字",dataset[mid])
        elif dataset[mid] > find_num :# 找的數在mid左面
            print("\033[31;1m找的數在mid[%s]左面\033[0m" % dataset[mid])
            return binary_search(dataset[0:mid], find_num)
        else:# 找的數在mid右面
            print("\033[32;1m找的數在mid[%s]右面\033[0m" % dataset[mid])
            return binary_search(dataset[mid+1:],find_num)
    else:
        if dataset[0] == find_num:  #find it
            print("找到數字啦",dataset[0])
        else:
            print("沒的分了,要找的數字[%s]不在列表里" % find_num)
 
 
binary_search(data,66)

九 匿名函數

匿名函數就是不需要顯式的指定函數

復制代碼
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
復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM