1. 程式人生 > >python簡單學------------python函式

python簡單學------------python函式

  • 如果在開發程式時,需要某塊程式碼多次,但是為了提高編寫的效率以及程式碼的重用,所以把具有獨立功能的程式碼塊組織為一個小模組,這就是函式

    函式定義和呼叫

    <1>定義函式

    定義函式的格式如下:

    
        def 函式名():
            程式碼
    

    demo:

    
        # 定義一個函式,能夠完成列印資訊的功能
        def printInfo(): print '------------------------------------' print ' 人生苦短,我用Python' print '------------------------------------' 

    <2>呼叫函式

    定義了函式之後,就相當於有了一個具有某些功能的程式碼,想要讓這些程式碼能夠執行,需要呼叫它

    呼叫函式很簡單的,通過 函式名() 即可完成呼叫

    demo:

    
        # 定義完函式後,函式是不會自動執行的,需要呼叫它才可以
        printInfo()
    

    函式的文件說明

    >>> def test(a,b): ... "用來完成對2個數求和" ... print("%d"%(a+b)) ... >>> >>> test(11,22) 33 

    如果執行,以下程式碼

    >>> help(test)
    

    能夠看到test函式的相關說明

    Help on function test in module __main__:
    
    test(a, b)
        用來完成對2個數求和
    (END)

 

 

函式引數(一)

 

思考一個問題,如下:

 

現在需要定義一個函式,這個函式能夠完成2個數的加法運算,並且把結果打印出來,該怎樣設計?下面的程式碼可以嗎?有什麼缺陷嗎?

   def add2num():
       a = 11 b = 22 c = a+b print c 

 

為了讓一個函式更通用,即想讓它計算哪兩個數的和,就讓它計算哪兩個數的和,在定義函式的時候可以讓函式接收資料,就解決了這個問題,這就是 函式的引數

 

<1> 定義帶有引數的函式

 

示例如下:

 

    def add2num(a, b):
        c = a+b
        print c 

 

<2> 呼叫帶有引數的函式

 

以呼叫上面的add2num(a, b)函式為例:

 


    def add2num(a, b):
        c = a+b
        print c add2num(11, 22) #呼叫帶有引數的函式時,需要在小括號中,傳遞資料 

 

呼叫帶有引數函式的執行過程:

<3> 呼叫函式時引數的順序

>>> def test(a,b): ... print(a,b) ... >>> test(1,2) 1 2 >>> test(b=1,a=2) 2 1 >>> >>> test(b=1,2) File "<stdin>", line 1 SyntaxError: positional argument follows keyword argument >>> >>> 

<4> 小總結

  • 定義時小括號中的引數,用來接收引數用的,稱為 “形參”
  • 呼叫時小括號中的引數,用來傳遞給函式用的,稱為 “實參”

函式返回值(一)

<1>“返回值”介紹

現實生活中的場景:

我給兒子10塊錢,讓他給我買包煙。這個例子中,10塊錢是我給兒子的,就相當於呼叫函式時傳遞到引數,讓兒子買菸這個事情最終的目標是,讓他把煙給你帶回來然後給你對麼,,,此時煙就是返回值

開發中的場景:

定義了一個函式,完成了獲取室內溫度,想一想是不是應該把這個結果給呼叫者,只有呼叫者擁有了這個返回值,才能夠根據當前的溫度做適當的調整

綜上所述:

  • 所謂“返回值”,就是程式中函式完成一件事情後,最後給呼叫者的結果

<2>帶有返回值的函式

想要在函式中把結果返回給呼叫者,需要在函式中使用return

如下示例:

    def add2num(a, b):
        c = a+b
        return c 

或者

    def add2num(a, b):
        return a+b 

<3>儲存函式的返回值

在本小節剛開始的時候,說過的“買菸”的例子中,最後兒子給你煙時,你一定是從兒子手中接過來 對麼,程式也是如此,如果一個函式返回了一個數據,那麼想要用這個資料,那麼就需要儲存

儲存函式的返回值示例如下:

    #定義函式
    def add2num(a, b): return a+b #呼叫函式,順便儲存函式的返回值 result = add2num(100,98) #因為result已經儲存了add2num的返回值,所以接下來就可以使用了 print result 

結果:

    198

4種函式的型別

函式根據有沒有引數,有沒有返回值,可以相互組合,一共有4種

  • 無引數,無返回值
  • 無引數,又返回
  • 有引數,無返回值
  • 有引數,有返回值

<1>無引數,無返回值的函式

此類函式,不能接收引數,也沒有返回值,一般情況下,列印提示燈類似的功能,使用這類的函式

    def printMenu():
        print('--------------------------') print(' xx涮涮鍋 點菜系統') print('') print(' 1. 羊肉涮涮鍋') print(' 2. 牛肉涮涮鍋') print(' 3. 豬肉涮涮鍋') print('--------------------------') 

結果:

無引數無返回值

<2>無引數,有返回值的函式

此類函式,不能接收引數,但是可以返回某個資料,一般情況下,像採集資料,用此類函式


    # 獲取溫度
    def getTemperature(): #這裡是獲取溫度的一些處理過程 #為了簡單起見,先模擬返回一個數據 return 24 temperature = getTemperature() print('當前的溫度為:%d'%temperature) 

結果:

    當前的溫度為: 24

<3>有引數,無返回值的函式

此類函式,能接收引數,但不可以返回資料,一般情況下,對某些變數設定資料而不需結果時,用此類函式

<4>有引數,有返回值的函式

此類函式,不僅能接收引數,還可以返回某個資料,一般情況下,像資料處理並需要結果的應用,用此類函式


    # 計算1~num的累積和
    def calculateNum(num): result = 0 i = 1 while i<=num: result = result + i i+=1 return result result = calculateNum(100) print('1~100的累積和為:%d'%result) 

結果:

    1~100的累積和為: 5050

<5>小總結

  • 函式根據有沒有引數,有沒有返回值可以相互組合
  • 定義函式時,是根據實際的功能需求來設計的,所以不同開發人員編寫的函式型別各不相同

 

函式的巢狀呼叫


    def testB():
        print('---- testB start----') print('這裡是testB函式執行的程式碼...(省略)...') print('---- testB end----') def testA(): print('---- testA start----') testB() print('---- testA end----') testA() 

結果:

    ---- testA start----
    ---- testB start----
    這裡是testB函式執行的程式碼...(省略)...
    ---- testB end----
    ---- testA end----

小總結:

  • 一個函式裡面又呼叫了另外一個函式,這就是所謂的函式巢狀呼叫 

  • 如果函式A中,呼叫了另外一個函式B,那麼先把函式B中的任務都執行完畢之後才會回到上次 函式A執行的位置

函式應用:列印圖形和數學計算

目標

  • 感受函式的巢狀呼叫
  • 感受程式設計的思路,複雜問題分解為簡單問題

思考&實現1

  1. 寫一個函式列印一條橫線
  2. 列印自定義行數的橫線

參考程式碼1


# 列印一條橫線
def printOneLine(): print("-"*30) # 列印多條橫線 def printNumLine(num): i=0 # 因為printOneLine函式已經完成了列印橫線的功能, # 只需要多次呼叫此函式即可 while i<num: printOneLine() i+=1 printNumLine(3) 

思考&實現2

  1. 寫一個函式求三個數的和
  2. 寫一個函式求三個數的平均值

參考程式碼2


# 求3個數的和
def sum3Number(a,b,c): return a+b+c # return 的後面可以是數值,也可是一個表示式 # 完成對3個數求平均值 def average3Number(a,b,c): # 因為sum3Number函式已經完成了3個數的就和,所以只需呼叫即可 # 即把接收到的3個數,當做實參傳遞即可 sumResult = sum3Number(a,b,c) aveResult = sumResult/3.0 return aveResult # 呼叫函式,完成對3個數求平均值 result = average3Number(11,2,55) print("average is %d"%result)


區域性變數

<1>什麼是區域性變數





<2>小總結

  • 區域性變數,就是在函式內部定義的變數
  • 不同的函式,可以定義相同的名字的區域性變數,但是各用個的不會產生影響
  • 區域性變數的作用,為了臨時儲存資料需要在函式中定義變數來進行儲存,這就是它的作用

 

全域性變數

<1>什麼是全域性變數

如果一個變數,既能在一個函式中使用,也能在其他的函式中使用,這樣的變數就是全域性變數

demo如下:


    # 定義全域性變數
    a = 100

    def test1(): print(a) def test2(): print(a) # 呼叫函式 test1() test2() 

執行結果:

<2>全域性變數和區域性變數名字相同問題

看如下程式碼:

<3>修改全域性變數

既然全域性變數,就是能夠在所以的函式中進行使用,那麼可否進行修改呢?

程式碼如下:

<4>總結1:

  • 在函式外邊定義的變數叫做全域性變數
  • 全域性變數能夠在所有的函式中進行訪問
  • 如果在函式中修改全域性變數,那麼就需要使用global進行宣告,否則出錯
  • 如果全域性變數的名字和區域性變數的名字相同,那麼使用的是區域性變數的,小技巧強龍不壓地頭蛇

<5>可變型別的全域性變數

>>> a = 1
>>> def f(): ... a += 1 ... print a ... >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'a' referenced before assignment >>> >>> >>> li = [1,] >>> def f2(): ... li.append(1) ... print li ... >>> f2() [1, 1] >>> li [1, 1] 

<5>總結2:

  • 在函式中不使用global宣告全域性變數時不能修改全域性變數的本質是不能修改全域性變數的指向,即不能將全域性變數指向新的資料。
  • 對於不可變型別的全域性變數來說,因其指向的資料不能修改,所以不使用global時無法修改全域性變數。
  • 對於可變型別的全域性變數來說,因其指向的資料可以修改,所以不使用global時也可修改全域性變數。

函式返回值(二)

在python中我們可不可以返回多個值?

>>> def divid(a, b): ... shang = a//b ... yushu = a%b ... return shang, yushu ... >>> sh, yu = divid(5, 2) >>> sh 5 >>> yu 1 

本質是利用了元組

函式引數(二)

1. 預設引數

呼叫函式時,預設引數的值如果沒有傳入,則被認為是預設值。下例會列印預設的age,如果age沒有被傳入:

def printinfo( name, age = 35 ): # 列印任何傳入的字串 print "Name: ", name print "Age ", age # 呼叫printinfo函式 printinfo(name="miki" ) printinfo( age=9,name="miki" ) 

以上例項輸出結果:

Name:  miki
Age  35
Name:  miki
Age  9

注意:帶有預設值的引數一定要位於引數列表的最後面。

>>> def printinfo(name, age=35, sex): ... print name ... File "<stdin>", line 1 SyntaxError: non-default argument follows default argument 

2.不定長引數

有時可能需要一個函式能處理比當初宣告時更多的引數。這些引數叫做不定長引數,宣告時不會命名。

基本語法如下:

    def functionname([formal_args,] *args, **kwargs):
       "函式_文件字串" function_suite return [expression] 

加了星號(*)的變數args會存放所有未命名的變數引數,args為元組;而加**的變數kwargs會存放命名引數,即形如key=value的引數, kwargs為字典。

>>> def fun(a, b, *args, **kwargs): ... """可變引數演示示例""" ... print "a =", a ... print "b =", b ... print "args =", args ... print "kwargs: " ... for key, value in kwargs.items(): ... print key, "=", value ... >>> fun(1, 2, 3, 4, 5, m=6, n=7, p=8) # 注意傳遞的引數對應 a = 1 b = 2 args = (3, 4, 5) kwargs: p = 8 m = 6 n = 7 >>> >>> >>> >>> c = (3, 4, 5) >>> d = {"m":6, "n":7, "p":8} >>> fun(1, 2, *c, **d) # 注意元組與字典的傳參方式 a = 1 b = 2 args = (3, 4, 5) kwargs: p = 8 m = 6 n = 7 >>> >>> >>> >>> fun(1, 2, c, d) # 注意不加星號與上面的區別 a = 1 b = 2 args = ((3, 4, 5), {'p': 8, 'm': 6, 'n': 7}) kwargs: >>> >>> 

3. 引用傳參

  • 可變型別與不可變型別的變數分別作為函式引數時,會有什麼不同嗎?
  • Python有沒有類似C語言中的指標傳參呢?
>>> def selfAdd(a): ... """自增""" ... a += a ... >>> a_int = 1 >>> a_int 1 >>> selfAdd(a_int) >>> a_int 1 >>> a_list = [1, 2] >>> a_list [1, 2] >>> selfAdd(a_list) >>> a_list [1, 2, 1, 2] 

Python中函式引數是引用傳遞(注意不是值傳遞)。對於不可變型別,因變數不能修改,所以運算不會影響到變數自身;而對於可變型別來說,函式體中的運算有可能會更改傳入的引數變數。

想一想為什麼

>>> def selfAdd(a): ... """自增""" ... a = a + a # 我們更改了函式體的這句話 ... >>> a_int = 1 >>> a_int 1 >>> selfAdd(a_int) >>> a_int 1 >>> a_list = [1, 2] >>> a_list [1, 2] >>> selfAdd(a_list) >>> a_list [1, 2] # 想一想為什麼沒有變呢?

遞迴函式

<1>什麼是遞迴函式

通過前面的學習知道一個函式可以呼叫其他函式。

如果一個函式在內部不呼叫其它的函式,而是自己本身的話,這個函式就是遞迴函式。

<2>遞迴函式的作用

舉個例子,我們來計算階乘 n! = 1 * 2 * 3 * ... * n

解決辦法1:

看階乘的規律

1! = 1
2! = 2 × 1 = 2 × 1!
3! = 3 × 2 × 1 = 3 × 2!
4! = 4 × 3 × 2 × 1 = 4 × 3!
...
n! = n × (n-1)!

解決辦法2:

 

匿名函式

用lambda關鍵詞能建立小型匿名函式。這種函式得名於省略了用def宣告函式的標準步驟。

lambda函式的語法只包含一個語句,如下:

    lambda [arg1 [,arg2,.....argn]]:expression

如下例項:

    sum = lambda arg1, arg2: arg1 + arg2

    #呼叫sum函式
    print "Value of total : ", sum( 10, 20 ) print "Value of total : ", sum( 20, 20 ) 

以上例項輸出結果:

    Value of total :  30
    Value of total :  40

Lambda函式能接收任何數量的引數但只能返回一個表示式的值

匿名函式不能直接呼叫print,因為lambda需要一個表示式

應用場合

函式作為引數傳遞

  1. 自己定義函式
    >>> def fun(a, b, opt): ... print "a =", a ... print "b =", b ... print "result =", opt(a, b) ... >>> fun(1, 2, lambda x,y:x+y) a = 1 b = 2 result = 3 
  2. 作為內建函式的引數

想一想,下面的資料如何指定按age或name排序?

stus = [
    {"name":"zhangsan", "age":18}, 
    {"name":"lisi", "age":19}, {"name":"wangwu", "age":17} ] 

按name排序:

>>> stus.sort(key = lambda x:x['name'])
>>> stus
[{'age': 19, 'name': 'lisi'}, {'age': 17, 'name': 'wangwu'}, {'age': 18, 'name': 'zhangsan'}] 

按age排序:

>>> stus.sort(key = lambda x:x['age'])
>>> stus
[{'age': 17, 'name': 'wangwu'}, {'age': 18, 'name': 'zhangsan'}, {'age': 19, 'name': 'lisi'}]

函式使用注意事項

1. 自定義函式

<1>無引數、無返回值

    def 函式名():
        語句

<2>無引數、有返回值

    def 函式名():
        語句
        return 需要返回的數值

注意:

  • 一個函式到底有沒有返回值,就看有沒有return,因為只有return才可以返回資料
  • 在開發中往往根據需求來設計函式需不需要返回值
  • 函式中,可以有多個return語句,但是隻要執行到一個return語句,那麼就意味著這個函式的呼叫完成

<3>有引數、無返回值

    def 函式名(形參列表):
        語句

注意:

  • 在呼叫函式時,如果需要把一些資料一起傳遞過去,被呼叫函式就需要用引數來接收
  • 引數列表中變數的個數根據實際傳遞的資料的多少來確定

<4>有引數、有返回值

    def 函式名(形參列表):
        語句
        return 需要返回的數值

<5>函式名不能重複

 

2. 呼叫函式

<1>呼叫的方式為:

    函式名([實參列表])

<2>呼叫時,到底寫不寫 實參

  • 如果呼叫的函式 在定義時有形參,那麼在呼叫的時候就應該傳遞引數

<3>呼叫時,實參的個數和先後順序應該和定義函式中要求的一致

<4>如果呼叫的函式有返回值,那麼就可以用一個變數來進行儲存這個值

3. 作用域

<1>在一個函式中定義的變數,只能在本函式中用(區域性變數)

 

<2>在函式外定義的變數,可以在所有的函式中使用(全域性變數)