9 - Python函數定義-位置參數-返回值

1 函數介紹

        函數在編程語言中就是完成特定功能的一個詞句組(代碼塊),這組語句能夠做爲一個單位使用,而且給它取一個名字。能夠經過函數名在程序的不一樣地方屢次執行(這叫函數的調用)。函數在編程語言中有基本分爲:預約義函數,自定義函數。預約義函數能夠直接使用,而自定義函數顧名思義須要咱們本身定義函數。編程

在數學中的定義,這裏就不介紹了。由於沒卵用。哈哈編程語言

1.1 爲何要使用函數

在編程中使用函數主要有兩個優勢:函數

  1. 下降編程難度:一般將一個複雜的大問題分解成一系列的小問題,而後將小問題劃分紅更小的問題,當問題細化爲足夠簡單時,咱們就能夠分而治之,各個小問題解決了,大問題就迎刃而解了。
  2. 代碼重用:避免重複勞做,提供效率
  3. 代碼更加簡潔美觀,可讀性增長

1.2 Python中的函數

        在Python中,函數由若干語句組成代碼塊函數名稱參數列表構成,它是組織代碼的最小單元,使用函數能夠完成必定的功能,在Python中函數主要分爲三類:內置函數第三方函數庫自定義函數。經常使用的內置函數在前面已經介紹,第三方函數庫須要先引入模塊,經過模塊調用,在模塊學習中進行介紹,這裏主要說的是如何自定義一個函數。學習

2 函數的基本使用

        在Python中,定義一個函數要使用def語句,依次寫出函數名括號括號中的參數和冒號:,而後,在縮進塊中編寫函數體,函數的返回值用return語句返回。下面是一個函數的基本結構ui

def 函數名(參數列表):
    函數體(代碼塊)
    [return 返回值]   # 函數能夠無返回值

注意:3d

  • 函數名就是標識符,命名要求同樣
  • 語句塊必須縮進,約定4個空格
  • Python的函數沒有return語句,隱式會返回一個None
  • 定義中的參數列表成爲形式函數,只是一種符號表達式(標識符),簡稱形參
    咱們以自定義一個求絕對值的函數爲例:
定義:
def abs(x):    
    if x >= 0:
        return x
    else:
        return -x

調用:
    abs(-10)

上面只是一個函數的定義,j具體來看一下各個部分的解釋:code

  • 函數名字叫作abs,接受1個形式參數x。
  • return x:表示要返回的值是x,函數能夠無返回值。
  • 函數是一個可調用對象,函數名加括號就表示調用。
  • 和變量是的使用方式相同,在使用函數時,須要預先進行定義。
  • 直接打印函數名,不會觸發函數的執行,反而會打印函數的內存地址。orm

    咱們自定義的函數abs,因爲與內置函數重名,那麼將會覆蓋掉內置函數,因此請謹慎命名。對象

        函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,並將結果返回。所以,函數內部經過條件判斷和循環能夠實現很是複雜的邏輯。若是沒有return語句,函數執行完畢後會隱士的返回None。若是咱們確實要return None能夠簡寫爲return,或者不寫return語句(會讓人看不懂,建議只寫return)。
        調用函數,那麼只須要使用函數名加括號,就能執行,但若是函數定義了參數,那麼必須在執行的時候傳遞參數給函授,不然會報異常!關於調用咱們還須要瞭解:

  1. 函數定義,只是聲明瞭一個函數,它不會被執行,調用時纔會執行
  2. 調用方式就是函數名後加上小括號,若是有必要須要在括號內寫上參數
  3. 調用時寫的參數是實際參數,是實實在在傳入的值,簡稱實參

    函數是可調用對象,可使用callable()進行判斷

In [1]: def abs(x):
   ...:     if x >= 1:
   ...:         return x
   ...:     else:
   ...:         return -x

In [2]: callable(abs)     # 函數是可調用的,注意這裏不能對函數加括號,那麼callable判斷的就是函數的返回值是否能夠執行了
Out[2]: True

In [3]: a = '123'
In [4]: callable(a)    # 字符串是不可調用的
Out[4]: False

3 函數的參數

        定義函數的時候,括號中指定的就是函數的參數(形式參數),當咱們調用函數時,須要將數據進行傳遞,這種傳遞參數的方式就叫作傳參,嚴格來講函數只可使用兩種方式:位置傳參關鍵字傳參

  1. 位置傳參:按照參數定義順序傳入實參
  2. 關鍵字傳參:使用形參的名字來傳入實參的方式

    須要注意的時:參數傳遞時若是使用形參的名字,那麼傳入參數的順序就能夠和定義的順序不一樣,當位置傳參和關鍵字傳參混用時,位置傳參必須放在關鍵字傳參前面傳入

定義函數function:
In [1]: def function(x,y):
   ...:     result = x + y
   ...:     return result
   ...:

位置傳參:
In [2]: function(1,2)    # 1對應x,2對應y。
Out[2]: 3

關鍵字傳參:
In [3]: function(y=1, x=2)   # 使用關鍵字時,參數能夠不用按照位置順序。
Out[3]: 3

混合傳參:
In [8]: function(1, y = 3)    # 混用時,關鍵字參數必需要再位置參數右邊
Out[8]: 4

3.1 參數的默認值

        在定義形式參數時,爲參數指定對應的值,就叫作參數的默認值,當定義了參數的默認值之後,咱們傳參時能夠選擇傳遞該參數的值,也能夠選擇不傳遞,當不傳遞此參數的值時,該參數就使用指定的默認值不然將會使用傳遞的值

參數默認值也屬於位置參數,只不過是給位置參數定義了默認值。

In [9]: def function(x = 10, y = 20):
   ...:     return x + y
   ...:

In [10]: function(2)   # 2會以位置參數的形式傳遞給x,y沒有傳遞,會使用默認值
Out[10]: 22

In [11]: function(y=100)  # x沒有傳遞,會使用默認值
Out[11]: 110

In [12]: function(x=100)  # y沒有傳遞,會使用默認值
Out[12]: 120

In [13]: function(20, y=500)  # 20以位置參數的形式傳遞給x,500以關鍵字參數的形式傳遞給了y
Out[13]: 520

當定義參數的默認值時,注意默認值參數必需要放在位置參數的右邊

In [1]: def functions(x=1, y):    # 必須把x=1,放在y的右邊,不然沒法完成函數定義
   ...:     print(x+y)
  File "<ipython-input-1-ea496fa7fc81>", line 1
    def functions(x=1, y):
                 ^
SyntaxError: non-default argument follows default argument

使用默認值參數的好處是:

  • 參數的默認值能夠在未傳入足夠的實參的時候,對沒有給定的參數賦值爲默認值。
  • 參數很是多的時候,並不須要用戶每次都輸入全部的參數,簡化函數調用。

3.2 可變參數

        可變參數顧名思義表示參數的數量是可變的,而且可使用一個形參匹配任意個實參。針對傳遞參數方式的不一樣又分爲可變位置傳參可變關鍵字傳參

3.2.1 可變位置傳參

        在形參前使用*號,表示該形參是可變參數,能夠接受多個實參,在函數內部,可變參數會封裝成元祖(即使是沒有傳遞)

In [15]: def function(*nums):
    ...:     print(nums)
    ...:

In [16]: function(1,2,3,4)  # 多個參數會被nums收集
(1, 2, 3, 4)

In [18]: function([1,2,3,4])  # 會把list收集成元祖類型
([1, 2, 3, 4],)

在函數定義時,通常的規範是使用 *args, 表示收集多個位置傳參。

3.2.2 可變關鍵字傳參

        在形參前使用**號,表示該形參是可變關鍵字參數,能夠接受多個關鍵字參數,在函數內部,可變關鍵字參數會封裝成字典(即使是沒有傳遞)

In [20]: def function(**kwargs):
    ...:     print(kwargs)
    ...:

In [21]: function(a=1,b=2)
{'a': 1, 'b': 2}


# 參數的默認值和位置參數同時使用
In [5]: def function(x=1,y=2,**kwargs):
   ...:     print('x = {}'.format(x))
   ...:     print('y = {}'.format(y))
   ...:     print(kwargs)
   ...:

In [6]: function(a=10,b=20)   # 參數沒有a,b形參,則被kwargs接收
x = 1
y = 2
{'a': 10, 'b': 20}

In [7]: function(x=100,y=200,z=300) # z沒有被匹配,被kwargs接收
x = 100
y = 200
{'z': 300}

In [8]: function(1000,2000,z=300)  # 前面的按照位置參數賦值,z一樣被字典kwargs收集
x = 1000
y = 2000
{'z': 300}

In [9]:

3.2.3 可變參數混合使用

        前面說的各類參數是能夠混合使用的,當混合使用時遵循必定的順序,簡單總結一下,按照從左至右的順序來講:位置參數,默認值參數,可變位置參數,可變關鍵字參數:def function(位置參數,默認值參數,可變位置參數,可變關鍵字參數)

不管如何,順序不能顛倒

In [9]: def function(x,y,z=1,*args,**kwargs):  # x,y,z都爲位置參數,z的默認值爲1,*args收集額外的位置傳參,kwargs收集額外的關鍵字傳參
   ...:     print(x,y,z)
   ...:     print(args)
   ...:     print(kwargs)
   ...:

In [10]: function(1,2,3,4,5,a=1,b=2)
1 2 3
(4, 5)
{'a': 1, 'b': 2}

3.2.4 可變參數小結

針對可變參數以及不一樣的混用方式能夠有以下結論:

  • 分爲位置可變參數關鍵字可變參數
  • 位置可變參數在形參前使用一個星號*
  • 關鍵字可變參數在形參前使用兩個星號**
  • 可變位置參數和可變關鍵字參數均可以收集若干個實參,可變位置參數收集造成一個tuple可變關鍵字參數收集造成一個dict
  • 混合使用參數的時候,在定義階段要遵循以下順序:位置參數默認值參數可變位置參數可變關鍵字參數

    當位置傳參和關鍵字傳參同時使用時,不能夠重複賦值!,這一點使用的時候很重要。

3.3 keyword-only參數*

        Python3的函數參數中,新增了keyword-only參數,什麼叫keyword-only參數?咱們說當在一個星號參數(可變位置參數)後,出現的普通參數,咱們稱它爲keyword-only參數,由於多餘的位置參數都會被*args收集,只能經過keyword的方式對這些形參進行賦值,因此它們只能使用'關鍵字傳參'。

In [11]: def function(a,b,c=1,*args,x,y=2,**kwargs):     # x,y是keyword-only參數,其中y存在默認值,能夠不用傳遞,x必須使用關鍵字的方式進行傳遞
    ...:     print(a,b,c)
    ...:     print(args)
    ...:     print(x,y)
    ...:     print(kwargs)
    ...:

In [12]: function(100,200,300,400,d=100,e=200)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-cf60009e3d1f> in <module>
----> 1 function(100,200,300,400,d=100,e=200)

TypeError: function() missing 1 required keyword-only argument: 'x'

In [13]: function(100,200,300,400,d=100,e=200,x=500)
100 200 300
(400,)
500 2
{'d': 100, 'e': 200}

特殊形式:

In [17]: def function(*,x,y):   
    ...:     print(x,y)
    ...:

In [18]: function(1,2,3,x=100,y=200)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-7d07ae79c088> in <module>
----> 1 function(1,2,3,x=100,y=200)

TypeError: function() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given


In [20]: function(x=100,y=200)
100 200

這裏*表示不接受位置傳參,只能使用關鍵字對參數進行賦值

注意:使用了keyword-only參數,那麼在定義形參的時的順序就有所改變了,它們是:位置參數,默認值參數,可變位置參數,keyword-only參數,可變關鍵字參數

3.4 參數解構

前面咱們說過Python的封裝與結構,這裏的參數也能夠利用這種思想進行結構,現有以下函數:

In [21]: def add(x=1,y=2):
    ...:     print(x+y)
    ...:

In [22]: t = (10,20)

In [23]: add(t[0],t[1])   # 將元祖的元素1和元素2分別傳給X,y
30

In [24]: add(*t)  
30

In [25]: d = {'x':100, 'y':200}
In [30]: add(**d)
300
  • 將t在傳遞參數時結構爲10,20,做爲位置傳參傳遞給add函數
  • 將d在傳遞參數時結構爲x=100,y=200,做爲關鍵字傳參傳遞給函數
  • 這種方法在後面函數的調用過程當中很是經常使用

如今再來回頭看一下,什麼時參數解構?

  1. 給函數提供實參的時候,能夠在集合類型前使用*或者**,把集合類型的結構解開,提取出因此的元素做爲函數的實參。
  2. 非字典類型使用*解構成位置參數
  3. 字典型使用**解構成關鍵字參數
  4. 提取出來的元素數目要和參數的要求匹配,也要和參數的類型匹配,不然請使用*args,**kwargs
In [31]: def add(a,b,*args,m,n,**kwargs):
    ...:     print(a+b+m+n)
    ...:

In [32]: dic = {'a':100,'b':200}
In [33]: add(**dic,m=300,n=400,x=1000)
1000

4 函數的返回值

        咱們一般編寫函數除了代碼能夠複用,更多的時候須要的是知道函數的運算結果,那麼函數把運算的結果返回給咱們,這個結果就叫做作函數的返回值。使用return關鍵字進行返回。

# 返回1個數據
In [34]: def add(x,y):
    ...:     result = x + y
    ...:     return result
    ...:

In [35]: a = add(10,20)
In [36]: print(a)
30


# 返回多個數據
In [37]: def add(x,y):
    ...:     result = x + y
    ...:     test = x * y
    ...:     return result,test
    ...:

In [38]: a = add(10,20)
In [39]: print(a)
(30, 200)


# 多個return語句
In [40]: def add(x,y):
    ...:     if x > 10:
    ...:         return y
    ...:     else:
    ...:         return x
    ...:

In [41]: a = add(10,20)
In [42]: print(a)
10

總結:

  1. Python函數使用return語句返回"返回值"
  2. 全部函數都有返回值,若是沒有return語句,隱式調用return None
  3. return語句並不必定是函數的語句塊的最後一條語句
  4. 一個函數能夠存在多個return語句,可是隻有一條能夠被執行,若是沒有一條return語句被執行,隱式調用return None
  5. return None能夠簡寫爲return
  6. 函數執行到return就會返回,因此return後面的語句永遠不會被執行
  7. return能夠理解爲,結束當前函數計算,返回值!

    多個返回值會被包裝成一個tuple進行返回,因此函數永遠只能返回一個數據

相關文章
相關標籤/搜索