在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 函數(shù)參數(shù)
基礎(chǔ)
itertools
HTTP 服務(wù)
hashlib
閉包
文件和目錄
單元測試
使用 @property
標(biāo)準(zhǔn)模塊
陌生的 metaclass
Base64
進(jìn)程、線程和協(xié)程
讀寫二進(jìn)制文件
匿名函數(shù)
輸入和輸出
Click
元組
字符編碼
partial 函數(shù)
參考資料
collections
協(xié)程
類和實(shí)例
Python 之旅
定制類和魔法方法
常用數(shù)據(jù)類型
繼承和多態(tài)
ThreadLocal
HTTP 協(xié)議簡介
Requests 庫的使用
讀寫文本文件
列表
os 模塊
迭代器 (Iterator)
正則表達(dá)式
集合
上下文管理器
異常處理
你不知道的 super
定義函數(shù)
datetime
資源推薦
字典
slots 魔法
hmac
第三方模塊
進(jìn)程
類方法和靜態(tài)方法
函數(shù)參數(shù)
高階函數(shù)
函數(shù)
re 模塊
高級特性
線程
argparse
生成器
結(jié)束語
字符串
map/reduce/filter
函數(shù)式編程
Celery
裝飾器

函數(shù)參數(shù)

在 Python 中,定義函數(shù)和調(diào)用函數(shù)都很簡單,但如何定義函數(shù)參數(shù)和傳遞函數(shù)參數(shù),則涉及到一些套路了??偟膩碚f,Python 的函數(shù)參數(shù)主要分為以下幾種:

  • 必選參數(shù)
  • 默認(rèn)參數(shù)
  • 可變參數(shù)
  • 關(guān)鍵字參數(shù)

必選參數(shù)

必選參數(shù)可以說是最常見的了,顧名思義,必選參數(shù)就是在調(diào)用函數(shù)的時(shí)候要傳入數(shù)量一致的參數(shù),比如:

>>> def add(x, y):        # x, y 是必選參數(shù)
...     print x + y
...
>>> add()                 # 啥都沒傳,不行
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (0 given)
>>> add(1)                # 只傳了一個(gè),也不行
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (1 given)
>>> add(1, 2)             # 數(shù)量一致,通過
3

默認(rèn)參數(shù)

默認(rèn)參數(shù)是指在定義函數(shù)的時(shí)候提供一些默認(rèn)值,如果在調(diào)用函數(shù)的時(shí)候沒有傳遞該參數(shù),則自動(dòng)使用默認(rèn)值,否則使用傳遞時(shí)該參數(shù)的值。

看看例子就明白了:

>>> def add(x, y, z=1):     # x, y 是必選參數(shù),z 是默認(rèn)參數(shù),默認(rèn)值是 1
...     print x + y + z
...
>>> add(1, 2, 3)            # 1+2+3
6
>>> add(1, 2)               # 沒有傳遞 z,自動(dòng)使用 z=1,即 1+2+1
4

可以看到,默認(rèn)參數(shù)使用起來也很簡單,但有兩點(diǎn)需要注意的是:

  • 默認(rèn)參數(shù)要放在所有必選參數(shù)的后面
  • 默認(rèn)參數(shù)應(yīng)該使用不可變對象

比如,下面對默認(rèn)參數(shù)的使用是錯(cuò)誤的:

>>> def add(x=1, y, z):      # x 是默認(rèn)參數(shù),必須放在所有必選參數(shù)的后面
...     return x + y + z
...
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>>
>>> def add(x, y=1, z):      # y 是默認(rèn)參數(shù),必須放在所有必選參數(shù)的后面
...     return x + y + z
...
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

再來看看為什么默認(rèn)參數(shù)應(yīng)該使用不可變對象。

我們看一個(gè)例子:

>>> def add_to_list(L=[]):
...     L.append('END')
...     return L

在上面的函數(shù)中,L 是一個(gè)默認(rèn)參數(shù),默認(rèn)值是 [],表示空列表。

我們來看看使用:

>>> add_to_list([1, 2, 3])          # 沒啥問題
[1, 2, 3, 'END']
>>> add_to_list(['a', 'b', 'c'])    # 沒啥問題
['a', 'b', 'c', 'END']
>>> add_to_list()                   # 沒有傳遞參數(shù),使用默認(rèn)值,也沒啥問題
['END']
>>> add_to_list()                   # 沒有傳遞參數(shù),使用默認(rèn)值,竟出現(xiàn)兩個(gè) 'END'
['END', 'END']
>>> add_to_list()                   # 糟糕了,三個(gè) 'END'
['END', 'END', 'END']

為啥呢?我們在調(diào)用函數(shù)的時(shí)候沒有傳遞參數(shù),那么就默認(rèn)使用 L=[],經(jīng)過處理,L 應(yīng)該只有一個(gè)元素,怎么會(huì)出現(xiàn)調(diào)用函數(shù)兩次,L 就有兩個(gè)元素呢?

原來,L 指向了可變對象 [],當(dāng)你調(diào)用函數(shù)時(shí),L 的內(nèi)容發(fā)生了改變,默認(rèn)參數(shù)的內(nèi)容也會(huì)跟著變,也就是,當(dāng)你第一次調(diào)用時(shí),L 的初始值是 [],當(dāng)你第二次調(diào)用時(shí),L 的初始值是 ['END'],等等。

所以,為了避免不必要的錯(cuò)誤,我們應(yīng)該使用不可變對象作為函數(shù)的默認(rèn)參數(shù)。

可變參數(shù)

在某些情況下,我們在定義函數(shù)的時(shí)候,無法預(yù)估函數(shù)應(yīng)該制定多少個(gè)參數(shù),這時(shí)我們就可以使用可變參數(shù)了,也就是,函數(shù)的參數(shù)個(gè)數(shù)是不確定的。

看看例子:

>>> def add(*numbers):
...     sum = 0
...     for i in numbers:
...         sum += i
...     print 'numbers:', numbers
...     return sum

在上面的代碼中,numbers 就是一個(gè)可變參數(shù),參數(shù)前面有一個(gè) * 號,表示是可變的。在函數(shù)內(nèi)部,參數(shù) numbers 接收到的是一個(gè) tuple。

在調(diào)用函數(shù)時(shí),我們可以給該函數(shù)傳遞任意個(gè)參數(shù),包括 0 個(gè)參數(shù):

>>> add()           # 傳遞 0 個(gè)參數(shù)
numbers: ()
0
>>> add(1)          # 傳遞 1 個(gè)參數(shù)
numbers: (1,)
1
>>> add(1, 2)       # 傳遞 2 個(gè)參數(shù)
numbers: (1, 2)
3
>>> add(1, 2, 3)    # 傳遞 3 個(gè)參數(shù)
numbers: (1, 2, 3)
6

上面的 * 表示任意參數(shù),實(shí)際上,它還有另外一個(gè)用法:用來給函數(shù)傳遞參數(shù)。

看看例子:

>>> def add(x, y, z):        # 有 3 個(gè)必選參數(shù)
...     return x + y + z
...
>>> a = [1, 2, 3]
>>> add(a[0], a[1], a[2])    # 這樣傳遞參數(shù)很累贅
6
>>> add(*a)                  # 使用 *a,相當(dāng)于上面的做法
6
>>> b = (4, 5, 6)
>>> add(*b)                  # 對元組一樣適用
15

再看一個(gè)例子:

>>> def add(*numbers):       # 函數(shù)參數(shù)是可變參數(shù)
...     sum = 0
...     for i in numbers:
...         sum += i
...     return sum
...
>>> a = [1, 2]
>>> add(*a)                  # 使用 *a 給函數(shù)傳遞參數(shù)
3
>>> a = [1, 2, 3, 4]
>>> add(*a)
10

關(guān)鍵字參數(shù)

可變參數(shù)允許你將不定數(shù)量的參數(shù)傳遞給函數(shù),而關(guān)鍵字參數(shù)則允許你將不定長度的鍵值對, 作為參數(shù)傳遞給一個(gè)函數(shù)。

讓我們看看例子:

>>> def add(**kwargs):
    return kwargs
>>> add()            # 沒有參數(shù),kwargs 為空字典
{}
>>> add(x=1)         # x=1 => kwargs={'x': 1}
{'x': 1}
>>> add(x=1, y=2)    # x=1, y=2 => kwargs={'y': 2, 'x': 1}
{'y': 2, 'x': 1}

在上面的代碼中,kwargs 就是一個(gè)關(guān)鍵字參數(shù),它前面有兩個(gè) * 號。kwargs 可以接收不定長度的鍵值對,在函數(shù)內(nèi)部,它會(huì)表示成一個(gè) dict。

和可變參數(shù)類似,我們也可以使用 **kwargs 的形式來調(diào)用函數(shù),比如:

>>> def add(x, y, z):
...     return x + y + z
...
>>> dict1 = {'z': 3, 'x': 1, 'y': 6}
>>> add(dict1['x'], dict1['y'], dict1['z'])    # 這樣傳參很累贅
10
>>> add(**dict1)        # 使用 **dict1 來傳參,等價(jià)于上面的做法
10

再看一個(gè)例子:

>>> def sum(**kwargs):               # 函數(shù)參數(shù)是關(guān)鍵字參數(shù)
...     sum = 0
...     for k, v in kwargs.items():
...         sum += v
...     return sum
>>> sum()                            # 沒有參數(shù)
0
>>> dict1 = {'x': 1}
>>> sum(**dict1)                     # 相當(dāng)于 sum(x=1)
1
>>> dict2 = {'x': 2, 'y': 6} 
>>> sum(**dict2)                     # 相當(dāng)于 sum(x=2, y=6)
8

參數(shù)組合

在實(shí)際的使用中,我們經(jīng)常會(huì)同時(shí)用到必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)或其中的某些。但是,需要注意的是,它們在使用的時(shí)候是有順序的,依次是必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)。

比如,定義一個(gè)包含上述四種參數(shù)的函數(shù):

>>> def func(x, y, z=0, *args, **kwargs):
    print 'x =', x
    print 'y =', y
    print 'z =', z
    print 'args =', args
    print 'kwargs =', kwargs

在調(diào)用函數(shù)的時(shí)候,Python 會(huì)自動(dòng)按照參數(shù)位置和參數(shù)名把對應(yīng)的參數(shù)傳進(jìn)去。讓我們看看:

>>> func(1, 2)                     # 至少提供兩個(gè)參數(shù),因?yàn)?x, y 是必選參數(shù)
x = 1
y = 2
z = 0
args = ()
kwargs = {}
>>> func(1, 2, 3)                  # x=1, y=2, z=3
x = 1
y = 2
z = 3
args = ()
kwargs = {}
>>> func(1, 2, 3, 4, 5, 6)         # x=1, y=2, z=3, args=(4, 5, 6), kwargs={}
x = 1
y = 2
z = 3
args = (4, 5, 6)
kwargs = {}
>>> func(1, 2, 4, u=6, v=7)        # args = (), kwargs = {'u': 6, 'v': 7}
x = 1
y = 2
z = 4
args = ()
kwargs = {'u': 6, 'v': 7}
>>> func(1, 2, 3, 4, 5, u=6, v=7)   # args = (4, 5), kwargs = {'u': 6, 'v': 7}
x = 1
y = 2
z = 3
args = (4, 5)
kwargs = {'u': 6, 'v': 7}

我們還可以通過下面的形式來傳遞參數(shù):

>>> a = (1, 2, 3)
>>> b = {'u': 6, 'v': 7}
>>> func(*a, **b)
x = 1
y = 2
z = 3
args = ()
kwargs = {'u': 6, 'v': 7}

小結(jié)

  • 默認(rèn)參數(shù)要放在所有必選參數(shù)的后面。
  • 應(yīng)該使用不可變對象作為函數(shù)的默認(rèn)參數(shù)。
  • *args 表示可變參數(shù),**kwargs 表示關(guān)鍵字參數(shù)。
  • 參數(shù)組合在使用的時(shí)候是有順序的,依次是必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)。
  • *args**kwargs 是 Python 的慣用寫法。

參考資料

上一篇:第三方模塊下一篇:元組