Python 從入門到進階之路(四)

以前的文章咱們簡單介紹了一下 Python 的幾種變量類型,本篇文章咱們來看一下 Python 中的函數。python

函數是組織好的,可重複使用的,用來實現單一,或相關聯功能的代碼段。express

函數能提升應用的模塊性,和代碼的重複利用率。你已經知道Python提供了許多內建函數,好比print()。但你也能夠本身建立函數,這被叫作用戶自定義函數。函數

你能夠定義一個由本身想要功能的函數,如下是簡單的規則:spa

  • 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()
  • 任何傳入參數和自變量必須放在圓括號中間,圓括號之間能夠用於定義參數。
  • 函數的第一行語句能夠選擇性地使用文檔字符串—用於存放函數說明。
  • 函數內容以冒號起始,而且縮進。
  • return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return至關於返回 None。

Python 定義函數使用 def 關鍵字,通常格式以下:code

1 def 函數名(參數列表):
2     函數體
1 def getNum():
2     pass

若是咱們定義了一個函數,裏面什麼也沒有寫,爲了避免讓代碼崩潰,咱們能夠寫一個 pass。blog

如今咱們來定義一個可執行的函數:內存

1 def getNum():
2     print(123)
3 getNum()  # 123

如上咱們定義了一個 getNum 的函數,函數內部 print 輸出 123,當咱們調用 getNum() 時,就會輸出 123。文檔

若是咱們不想輸出固定的 123,輸出結果有咱們本身定義,咱們能夠經過傳參的形式解決:字符串

def getNum(num):
    print(num)
    print(num * 2)
getNum(123)  # 123 246

能夠經過 return 的方式把想要的結果 return 出來:get

1 def getNum(num):
2     return num
3 print(getNum(123))  # 123

函數中也可使用嵌套函數的方式:

1 def getNum(num):
2     getName(num)
3 
4 def getName(name):
5     print(name)
6 
7 getNum("zhangsan")  # zhangsan

咱們經過向函數傳值來獲取咱們的結果,也能夠經過設置變量的形式來解決:

num = 1
def getNum():
    print(num)

getNum()  # 1

上面的代碼咱們設置了一個全局變量,固然咱們也能夠在函數內部設置變量,叫作局部變量,這樣更有利於咱們對本身函數內的變量操做而不去改變全局的變量,以下:

1 def getNum():
2     name = "zhangsan"
3     print(name)
4 
5 getNum()  # zhangsan

 在有的時候,咱們能夠直接將函數內的參數設置默認值,這就就能夠避免在沒有傳入該參數時函數報錯:

1 def getNum(a, b, c=11, d=22):
2     print(a)
3     print(b)
4     print(c)
5     print(d)
6 
7 getNum(1, 2, 3)  # 1 2 3 22

在上面的代碼中,咱們對函數 getNum 的第三個和第四個參數設置了默認值,在調用該函數時,咱們傳入了三個值,而後輸出結果發現,第三個參數的默認值被調用 getNum 時傳入的參數值覆蓋掉了,而第四個參數值因爲沒有傳入,因此使用了默認值 d=22。由此咱們能夠得出,當咱們不傳入對應參數值時若是設置默認值則使用默認值,若是傳入了參數值則優先使用傳入的參數值。

 

在上面的代碼中,咱們定義的參數都是單一的字符串或者數字,咱們也能夠定義列表,元組,字典這樣的參數,以下:

 1 list = [11, 22, 33]
 2 tuple = (44, 55, 66)
 3 dict = {"a": "77", "b": 88, "c": 99}
 4 
 5 def getTest(list, tuple, dict):
 6     print(list)
 7     print(tuple)
 8     print(dict)
 9 
10 getTest(list, tuple, dict)
11 '''
12 [11, 22, 33]
13 (44, 55, 66)
14 {'a': '77', 'b': 88, 'c': 99}
15 '''

在上面的代碼中咱們能夠看出,Python 中的不一樣變量類型均可以做爲參數傳入函數中。

接下來咱們再來看一下函數中缺省參數的 *args 和 **kwargs

1 def getTest(a, b, c=123, *args):
2     print(a)  # 11
3     print(b)  # 22
4     print(c)  # 33
5     print(args)  # (44, 55, 66)
6 
7 getTest(11, 22, 33, 44, 55, 66)

在上面的代碼中,print(c) 結果爲 33,這個咱們再上面已經解釋過了,可是咱們在參數 c 後面又加入了一個 *args 的形參,而後咱們在調用 getTest() 時向函數內部傳入參數的個數爲 6 個,而函數體 getTest() 接收的參數爲 4 個,按咱們上面叫的函數方法,理論上程序應該報錯,然而程序卻能運行,運行結果打印的第 4 個參數結果爲一個元組,將形參按順序對應的參數對應完畢以後剩餘的內容組成一個元組輸出。其中 *args 能夠寫成 *xxx,咱們習慣上命名爲 *args。

在函數傳參時,除了 *args 外還有一個 **kwargs,以下:

1 def getTest(a, b, c=123, *args, **kwargs):
2     print(a)  # 11
3     print(b)  # 22
4     print(c)  # 33
5     print(args)  # (44, 55, 66)
6     print(kwargs)  # {'name': 'zhangsan', 'age': 30}
7 
8 getTest(11, 22, 33, 44, 55, 66, name="zhangsan", age=30)

 

上面的代碼中,咱們在函數 getTest() 後面又多家了一個形參 **kwargs,當咱們在調用 getTest() 函數並傳入參數時,咱們傳入了 name="zhangsan" 這樣的鍵值對,這樣在打印輸出 **kwargs 時會轉爲一個字典類型的數據。其中 **kwargs 能夠寫成 **xxx,咱們習慣上命名爲 **kwargs。

注意:在print() 輸出時,*args 和 **kwargs 的 * 不須要寫。

根據上面的 *args 和 **kwargs,咱們如今來向這樣一個問題,加入我先在外面分別定義了一個元組類型變量 tuple 和字典類型數據 dict,而後調用 getTest() 函數時將變量傳入,輸出結果仍是跟上面的結果同樣,即下面的代碼:

 1 def getTest(a, b, c=123, *args, **kwargs):
 2     print(a)  # 11
 3     print(b)  # 22
 4     print(c)  # 33
 5     print(args)  # ((44, 55, 66), {'name': 'zhangsan', 'age': 30})
 6     print(kwargs)  # {}
 7 
 8 tuple=(44,55,66)
 9 dict={'name': 'zhangsan', 'age': 30}
10 getTest(11, 22, 33, tuple, dict)

當咱們仍是按照上面的 *args 和 **kwargs 寫法寫時,發現參數 tuple 和 dict 被當作一個數據輸出到了 *args 裏,這是因爲當咱們傳入 tuple 和 dict 時被當作了一個總體,咱們能夠在傳入前先將其解構一下就能夠了,以下:

 1 def getTest(a, b, c=123, *args, **kwargs):
 2     print(a)  # 11
 3     print(b)  # 22
 4     print(c)  # 33
 5     print(args)  # (44, 55, 66)
 6     print(kwargs)  # {'name': 'zhangsan', 'age': 30}
 7 
 8 tuple=(44,55,66)
 9 dict={'name': 'zhangsan', 'age': 30}
10 getTest(11, 22, 33, *tuple, **dict)

如上,咱們在傳入參數的時候傳入 *tuple 和 **dict 就能夠解決了,可是若是咱們在傳入參數時和調用時都不加 * 不就至關於把整個變量做爲參數了嗎?以下:

 1 def getTest(a, b, c=123, tuple, dict):
 2     print(a)
 3     print(b)
 4     print(c)
 5     print(tuple)
 6     print(dict)
 7 
 8 tuple=(44,55,66)
 9 dict={'name': 'zhangsan', 'age': 30}
10 getTest(11, 22, 33, tuple, dict)  # SyntaxError: non-default argument follows default argument

咱們會發現不寫 * 的話會報錯,緣由是當咱們在函數中定義默認參數時,默認參數必須寫在最後面,即 c=123 需寫在最後面,以下:

 1 def getTest(a, b, tuple, dict, c=123):
 2     print(a)  # 11
 3     print(b)  # 22
 4     print(c)  # 33
 5     print(tuple)  # (44, 55, 66)
 6     print(dict)  # {'name': 'zhangsan', 'age': 30}
 7 
 8 tuple=(44,55,66)
 9 dict={'name': 'zhangsan', 'age': 30}
10 getTest(11, 22, tuple, dict, 33)  

可是若是參數中存在 * 的話默認參數不能寫在最後面,以下:

 1 def getTest(a, b, *tuple, **dict, c=123):
 2     print(a)
 3     print(b)
 4     print(c)
 5     print(tuple)
 6     print(dict)
 7 
 8 tuple=(44,55,66)
 9 dict={'name': 'zhangsan', 'age': 30}
10 getTest(11, 22, *tuple, **dict, 33)  # SyntaxError: invalid syntax

由此咱們得出函數的傳參順序爲:參數,默認參數,*args,**kwargs。

 

咱們接下來看一下匿名函數。

python 使用 lambda 來建立匿名函數。

所謂匿名,意即再也不使用 def 語句這樣標準的形式定義一個函數。

  • lambda 只是一個表達式,函數體比 def 簡單不少。
  • lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
  • lambda 函數擁有本身的命名空間,且不能訪問本身參數列表以外或全局命名空間裏的參數。
  • 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增長運行效率。

lambda 函數的語法只包含一個語句,以下:

lambda [arg1 [,arg2,.....argn]]:expression
1 # 實現一個兩數相加的匿名函數
2 sum = lambda num1, num2: num1 + num2
3 print(sum(10, 20))  # 30
相關文章
相關標籤/搜索