Python 函數

函數


當編寫的代碼出現有規律的重複時,這個時候就要考慮定義函數,將這些代碼提取定義成一個函數,方便調用。html

Python 提供許多內置函數,能夠根據須要調用相應的函數實現想要的功能。一樣 Python 也可以靈活地自定義函數。python

調用函數


介紹如何定義函數前,先講下如何調用函數。微信

Python 提供許多內置函數,這些函數都是能夠直接調用的。包括前面的篇幅,其實也有調用函數實現一些功能。這裏大體講下函數的調用。app

舉個例子,求絕對值的函數 abs(),這個函數只接受一個參數。函數的使用能夠查看官方文檔:ide

http://docs.python.org/3/library/functions.html#abs函數

也能夠在交互式命令行下經過 help(abs) 來查看 abs 函數的幫助信息。測試

如今嘗試調用 abs() 函數:ui

>>> abs(-1)
1
>>> abs(1)
1

由於 abs 只接受一個參數,如果傳入的參數個數不爲 1,會報 TypeError 的錯誤,信息中也會給出錯誤的提示:idea

>>> abs(-1, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)

這裏表示,abs() 函數只接受一個參數,可是卻提供了兩個參數。命令行

abs() 的參數接收的是數值,如果傳入的類型錯誤,一樣也會報錯:

>>> abs('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'

這裏給出的錯誤提示表示 str 不是可接受的類型。

這就是函數調用,同時也須要注意的一些地方。要了解函數調用須要的幾個參數,以及參數的類型。

定義函數


如今講一下函數的定義,函數定義要使用 def 語句,後面緊跟的是函數名,括號,包含在括號內的參數以及冒號,而後在縮進塊編寫函數體,若是有返回值的話,則使用 return 語句返回。

仍是以求絕對值爲例,這裏自定義函數實現:

def my_abs(num):
    if num >= 0:
        return num
    else:
        return -num

當執行 return 時,函數即爲執行完畢,直接返回結果。例子中,簡單使用了條件判斷,函數內部能夠經過使用條件判斷以及循環,實現很是複雜的邏輯。

有些函數並無 return 語句。可是函數執行完畢後一樣會返回結果,只是結果爲 None。因此 return None,也能夠寫爲 return

如今咱們嘗試調用本身編寫的函數 my_abs:

>>> my_abs(1)
1
>>> my_abs(-1)
1
>>> my_abs('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in my_abs
TypeError: '>=' not supported between instances of 'str' and 'int'

這裏會看到當參數接受字符串的時候,出現的錯誤與 Python 提供的 abs 出錯信息不同。

這裏咱們添加對參數的檢查,只容許整數和浮點數類型的參數。能夠用 isinstance() 函數實現數據類型檢查。

>>> def my_abs(num):
...     if not isinstance(num, (int, float)):
...         raise TypeError("bad operand type")
...     if num >= 0:
...         return num
...     else:
...         return -num
...

再次嘗試調用該函數:

>>> my_abs('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in my_abs
TypeError: bad operand type

這樣,看起來就更像 abs() 函數。

pass 語句

有時候,可能並無想好要編寫怎樣的函數,可是想先定義,在後續補充代碼。這個時候,pass 語句就派上用場。

pass 語句可以作佔位符使用,能夠在函數體中先將這個語句放進來,讓編寫的其餘代碼運行起來。等到後續要補充的時候再去掉 pass 語句進行修改。例如:

def no_idea():
    pass

這裏若是函數體內沒有這個 pass 語句,運行就會提示有語法錯誤。

返回多個值

上面說起的自定義函數,包括帶 pass 語句的空函數(返回的是 None),返回的是一個值。

爲了能夠返回多個值,能夠直接返回一個元組,例如:

>>> def my_func():
...     return 1, 2, 3
...
>>> a, b, c = my_func()
>>> a
1
>>> b
2
>>> c
3

雖然上面的函數看上去是返回了多個值,但其實是先建立一個元組而後返回的。

其實咱們使用的是逗號來生成一個元組,而不是用括號。例如:

>>> a = (1,2) # 帶括號
>>> a
(1, 2)
>>> b = 1,2 # 不帶括號
>>> b
(1, 2)

因此,這前面定義返回多值的函數,其實返回的是元組。如果賦值給單個變量,那麼這個變量其實就是返回的那個元組自己:

>>> d = my_func()
>>> d
(1, 2, 3)

函數參數


位置參數

先定義一個函數:

>>> def func(a, b):
...     print('a = {},b = {}'.format(a, b))
...
>>> func(1,2)
a = 1,b = 2

在這裏,就是 ab,兩個參數都是位置參數,調用的時候,依次將兩個值按照順序依次賦值給參數 ab

默認參數

延用上面的例子,在這裏,咱們調用的時候只賦值給 a:

>>> func(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() missing 1 required positional argument: 'b'

這裏錯誤提示:調用參數缺乏一個位置參數 b

這個時候,就能夠考慮使用默認參數:

>>> def func(a, b=2):
...     print('a = {}, b = {}'.format(a, b))
...
>>> func(1)
a = 1, b = 2

能夠看到當調用 func(1) 時,就至關於調用了 func(1, 2)

這裏有些地方須要注意:

  • 必選的參數必定要放在默認參數前面,不然會報錯。
  • 默認參數必須指向不變對象

第一點比較好理解,若是默認參數在必選參數前面,因爲傳入的值會按照位置給參數賦值。例以下面的錯誤示例(下面這種寫法僅作錯誤示範,不建議如此編寫。固然這樣編寫也會報錯):

def func(a=1, b):
    return a, b

假設咱們調用的時候,以這樣的邏輯想,如今 a 有默認值,只給 b 賦值就能夠了。可是賦值會按照位置賦值。好比調用 func(2),其實這裏是將 2 賦值給了 a,替代了原來的 1,最終 b 仍是缺乏賦值。

第二點,必須指向不變對象,千萬不能像下面這樣編寫代碼:

def func(a, b=[]):
    ....

這樣寫的話,後面會遇到不少的麻煩。b 做爲可修改的對象,這些修改會影響到下次調用這個函數的默認值。好比:

>>> def func(a, b=[]):
...     print(b)
...     return b
...
>>> x = func(1)
[]
>>> x.append(2)
>>> x.append('wow!')
>>> x
[2, 'wow!']
>>> func(1)
[2, 'wow!']

能夠看到當再次調用 func(1) 的時候,結果已經變了,這個並非原來的初衷。

若是真的須要使用列表,最好先使用 None,而後在函數裏面用相應的邏輯檢查。

固然測試 None 的時候要須要注意,使用 is 操做符是很是重要的。

def func(a, b=None):
    if not b: # 不建議這樣寫,建議用 b is None:代替
        b = []

上面不建議使用 if not b: ,若是這樣的話,None 會被當成是 False,而長度爲 0 的字符串,列表,元組,字典等均可能被當成 False。這一點也要注意。

可變參數

上面說起的函數都是固定數量的位置參數,爲了實現一個能接受任意數量的位置參數的函數,可使用一個 * 參數。例如:

>>> def func(*nums):
...     sum = 0
...     for num in nums:
...         sum += num
...     return sum
...

>>> func(1,2)
3
>>> func(1,2,3)
6

這樣就實現了能夠傳入任意數量的參數的位置參數。

關鍵字參數

如果要實現接受任意數量的關鍵字參數,可使用 ** 開頭的參數。好比:

>>> def info(name, age, **kw):
...     print('name:', name, 'age:', age, 'other:', kw)
...
>>> info('大夢三千秋', 0)
name: 大夢三千秋 age: 0 other: {} 
>>> info('大夢三千秋', 0, city='Guangzhou')
name: 大夢三千秋 age: 0 other: {'city': 'Guangzhou'}
>>> info('大夢三千秋', 0, city='Guangzhou', gender='male')
name: 大夢三千秋 age: 0 other: {'city': 'Guangzhou', 'gender': 'male'}

這樣就實現了傳入任意個數的關鍵字參數。這裏,關鍵字參數容許傳入 0 個或任意個參數名的參數,函數內部會自動組成一個 dict,如上示例。

命名關鍵字參數

命名關鍵字參數,實際上是將關鍵字參數放到某個 * 參數後面或者單個 * 後面,例如:

>>> def info(name, age, *, city):
...     print(name, age, city)
...
>>> info('大夢三千秋', 0, city='Guangzhou')
大夢三千秋 0 Guangzhou

這裏注意調用方式,必定要傳入參數名,如果沒有傳入參數名,則會報錯:

>>> info('大夢三千秋', 0, 'Guangzhou')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: info() takes 2 positional arguments but 3 were given

上面的提示中說只須要 2 個位置參數,可是傳入的參數有 3 個。這時由於缺乏參數名 city,解釋器將 3 個參數都視爲位置參數,但 info 函數只接受 2 個位置參數。

參數順序

這裏說起到的參數有位置(必選)參數、默認參數、可變參數、關鍵字參數和命名關鍵字參數。可是須要注意參數的定義順序:

必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。

雖然上面的參數均可以組合在一塊兒,可是不建議這樣作,這樣會致使可理解性變差。


以上就是關於函數的定義,調用以及函數參數的一些內容。

歡迎關注微信公衆號《書所集錄》
相關文章
相關標籤/搜索