成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Python: 函數(shù)參數(shù)魔法

zxhaaa / 2683人閱讀

摘要:在調(diào)用函數(shù)時(shí),我們可以給該函數(shù)傳遞任意個(gè)參數(shù),包括個(gè)參數(shù)傳遞個(gè)參數(shù)傳遞個(gè)參數(shù)傳遞個(gè)參數(shù)傳遞個(gè)參數(shù)上面的表示任意參數(shù),實(shí)際上,它還有另外一個(gè)用法用來(lái)給函數(shù)傳遞參數(shù)。應(yīng)該使用不可變對(duì)象作為函數(shù)的默認(rèn)參數(shù)。

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

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

必選參數(shù)

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

可變參數(shù)

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

必選參數(shù)

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

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

默認(rèn)參數(shù)是指在定義函數(shù)的時(shí)候提供一些默認(rèn)值,如果在調(diào)用函數(shù)的時(shí)候沒(méi)有傳遞該參數(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)               # 沒(méi)有傳遞 z,自動(dòng)使用 z=1,即 1+2+1
4

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

默認(rèn)參數(shù)要放在所有必選參數(shù)的后面

默認(rèn)參數(shù)應(yīng)該使用不可變對(duì)象

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

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

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

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

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

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

我們來(lái)看看使用:

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

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

原來(lái),L 指向了可變對(duì)象 [],當(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)該使用不可變對(duì)象作為函數(shù)的默認(rèn)參數(shù)。

可變參數(shù)

在某些情況下,我們?cè)诙x函數(shù)的時(shí)候,無(wú)法預(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è) * 號(hào),表示是可變的。在函數(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è)用法:用來(lái)給函數(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)                  # 對(duì)元組一樣適用
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ù)則允許你將不定長(zhǎng)度的鍵值對(duì), 作為參數(shù)傳遞給一個(gè)函數(shù)。

讓我們看看例子:

>>> def add(**kwargs):
    return kwargs
>>> add()            # 沒(méi)有參數(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è) * 號(hào)。kwargs 可以接收不定長(zhǎng)度的鍵值對(duì),在函數(shù)內(nèi)部,它會(huì)表示成一個(gè) dict。

和可變參數(shù)類(lèi)似,我們也可以使用 **kwargs 的形式來(lái)調(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 來(lái)傳參,等價(jià)于上面的做法
10

再看一個(gè)例子:

>>> def sum(**kwargs):               # 函數(shù)參數(shù)是關(guān)鍵字參數(shù)
...     sum = 0
...     for k, v in kwargs.items():
...         sum += v
...     return sum
>>> sum()                            # 沒(méi)有參數(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ù)或其中的某些。但是,需要注意的是,它們?cè)谑褂玫臅r(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ù)名把對(duì)應(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}

我們還可以通過(guò)下面的形式來(lái)傳遞參數(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)該使用不可變對(duì)象作為函數(shù)的默認(rèn)參數(shù)。

*args 表示可變參數(shù),**kwargs 表示關(guān)鍵字參數(shù)。

參數(shù)組合在使用的時(shí)候是有順序的,依次是必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)。

*args**kwargs 是 Python 的慣用寫(xiě)法。

本文由 funhacks 發(fā)表于個(gè)人博客,采用 Creative Commons BY-NC-ND 4.0(自由轉(zhuǎn)載-保持署名-非商用-禁止演繹)協(xié)議發(fā)布。
非商業(yè)轉(zhuǎn)載請(qǐng)注明作者及出處。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者本人。
本文標(biāo)題為: Python: 函數(shù)參數(shù)魔法
本文鏈接為: https://funhacks.net/2016/12/...

參考資料

args 和 *kwargs · Python進(jìn)階

函數(shù)的參數(shù) - 廖雪峰的官方網(wǎng)站

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44324.html

相關(guān)文章

  • Python & IPython Notebook 代碼計(jì)時(shí)與簡(jiǎn)單的性能分析

    摘要:本文記錄一些用于代碼計(jì)時(shí)和簡(jiǎn)單性能分析的工具。也就是這個(gè)魔法命令把中剩余的代碼作為輸入變量,對(duì)其進(jìn)行計(jì)時(shí)。該命令會(huì)運(yùn)行最后一個(gè)參數(shù)指定的代碼,然后在運(yùn)行時(shí)分析所有需要分析的函數(shù)。該命令運(yùn)行之后會(huì)打印一個(gè)逐行分析報(bào)告。 本文記錄一些用于 Python 代碼計(jì)時(shí)和簡(jiǎn)單性能分析的工具。強(qiáng)烈推薦后兩種工具。 begin & end 手動(dòng)計(jì)時(shí) Matlab 里有一對(duì) tic toc 命令,使用格...

    betacat 評(píng)論0 收藏0
  • 經(jīng)驗(yàn)拾憶(純手工)=> Python__黑魔法__

    摘要:類(lèi)的繼承類(lèi)繼承有三種調(diào)用方式,其實(shí)是有區(qū)別的,聽(tīng)我慢慢道來(lái)第一種父類(lèi)方法參數(shù)直接調(diào)用第二種方法參數(shù)直接調(diào)用在誰(shuí)的類(lèi)下調(diào)用,就找此類(lèi)對(duì)應(yīng)的下一個(gè)就是要繼承的第三種方法參數(shù)找類(lèi)名對(duì)應(yīng)的的下一個(gè),就是繼承的,一般寫(xiě)本身的類(lèi)名上下文管理器上下文管理 類(lèi)的繼承 類(lèi)繼承有三種調(diào)用方式,其實(shí)是 有區(qū)別 的,聽(tīng)我慢慢道來(lái) class A: def say(self, name): ...

    tulayang 評(píng)論0 收藏0
  • python 類(lèi)和元類(lèi)(metaclass)的理解和簡(jiǎn)單運(yùn)用

    摘要:什么是元類(lèi)剛才說(shuō)了,元類(lèi)就是創(chuàng)建類(lèi)的類(lèi)。類(lèi)上面的屬性,相信愿意了解元類(lèi)細(xì)節(jié)的盆友,都肯定見(jiàn)過(guò)這個(gè)東西,而且為之好奇。使用了這個(gè)魔法方法就意味著就會(huì)用指定的元類(lèi)來(lái)創(chuàng)建類(lèi)了。深刻理解中的元類(lèi) (一) python中的類(lèi) 今天看到一篇好文,然后結(jié)合自己的情況總結(jié)一波。這里討論的python類(lèi),都基于python2.7x以及繼承于object的新式類(lèi)進(jìn)行討論。 首先在python中,所有東西都...

    zhangqh 評(píng)論0 收藏0
  • python魔法算法詳解

    摘要:據(jù)說(shuō),的對(duì)象天生擁有一些神奇的方法,它們總被雙下劃線(xiàn)所包圍,他們是面向?qū)ο蟮牡囊磺?。的魔術(shù)方法非常強(qiáng)大,然而隨之而來(lái)的則是責(zé)任。 據(jù)說(shuō),Python 的對(duì)象天生擁有一些神奇的方法,它們總被雙下劃線(xiàn)所包圍,他們是面向?qū)ο蟮?Python 的一切。 他們是可以給你的類(lèi)增加魔力的特殊方法,如果你的對(duì)象實(shí)現(xiàn)(重載)了這些方法中的某一個(gè),那么這個(gè)方法就會(huì)在特殊的情況下被 Python 所調(diào)用,你...

    孫吉亮 評(píng)論0 收藏0
  • Python “黑魔法” 之 Meta Classes

    摘要:幸而,提供了造物主的接口這便是,或者稱(chēng)為元類(lèi)。接下來(lái)我們將通過(guò)一個(gè)栗子感受的黑魔法,不過(guò)在此之前,我們要先了解一個(gè)語(yǔ)法糖。此外,在一些小型的庫(kù)中,也有元類(lèi)的身影。 首發(fā)于 我的博客 轉(zhuǎn)載請(qǐng)注明出處 接觸過(guò) Django 的同學(xué)都應(yīng)該十分熟悉它的 ORM 系統(tǒng)。對(duì)于 python 新手而言,這是一項(xiàng)幾乎可以被稱(chēng)作黑科技的特性:只要你在models.py中隨便定義一個(gè)Model的子類(lèi),Dj...

    LeoHsiun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<