Python?調(diào)用函數(shù)時可使用的正式參數(shù)類型:
? ??必需參數(shù) (位置參數(shù))峭拘、關(guān)鍵字參數(shù) (key=value)、默認(rèn)參數(shù) (key=default)狮暑、不定長參數(shù)(可變參數(shù))鸡挠、強制位置參數(shù)(組合傳參)
? ??Tips:有興趣的還可以了解一下什么是形參?什么是實參搬男?
不定長參數(shù)? *args **kwargs
? ? Python 在定義函數(shù)的過程中拣展,當(dāng)你可能需要一個函數(shù)能處理比當(dāng)初聲明時更多的參數(shù)。那么就會用到 *arg缔逛、**kwargs 稱之為不定長參數(shù)备埃,聲明時不會命名;
? ? *args 具體語法操作如下:
def func(a, *args):
????print(a)
????print(args)func(1, 2)
結(jié)果輸出:
1
(2,)注意:加了星號?*?的參數(shù)會以元組(tuple)的形式導(dǎo)入译株,存放所有未命名的變量參數(shù)瓜喇。?
如果在函數(shù)調(diào)用時沒有指定參數(shù),它就是一個空元組:
def func(a, *args):
?????print(a)
?????print(args)func(10)
func(1, 2)結(jié)果輸出:
結(jié)果:
10
()
結(jié)果:
1
(2,)
從上面的示例來看歉糜,如果傳入的參數(shù)超過了位置參數(shù)乘寒,后面的參數(shù)都會以元組的來接收,那么如果我們直接傳入一個元組參數(shù)行不行匪补?
t = (1, 2, 3)
def func(a, *args):
?????print('結(jié)果:')
?????print(a)
?????print(args)func(1, 2, t )
結(jié)果:
1
(2, (1, 2, 3))
從以上示例來看目前是可以的伞辛,但是如果我們需要對參數(shù)進(jìn)行計算或者其他操作的時候呢?下面再來看一個列子:
t = (1, 2, 3)
def avg(a, *args):
?????return (a + sum(args)) / (len(args) + 1)print(avg(20, t))
結(jié)果:
????TypeError: unsupported operand type(s) for +: 'int' and 'tuple'
結(jié)果就報錯了夯缺,原因是因為你直接傳入的是一個元組蚤氏,int類型和元組是不能直接進(jìn)行計算的,那么怎么解決這個問題踊兜?其實很簡單看下面的實例:
t = (1, 2, 3)
def avg(a, *args):??????
????return (a + sum(args)) / (len(args) + 1)print(avg(20, *t))
結(jié)果:???
6.5
其實很簡單竿滨,只需要在傳 t 元組的時候加上一個 * 就可以了,稱之為解包捏境,就是把元組打散于游,分開傳入.
*kwargs 具體語法操作如下:
d = {'name': 'amy', 'age': 18}
t = (1, 2, 3)def func(a, *args, **kwargs):
?????print('結(jié)果:')
?????print(f'位置參數(shù):{a}')
?????print(f'不定長元組參數(shù):{args}')
?????print(f'不定長鍵值對參數(shù):{kwargs}')func(1, t, d)
結(jié)果:
位置參數(shù):1
不定長元組參數(shù):((1, 2, 3), {'name': 'amy', 'age': 18})
不定長鍵值對參數(shù):{}
咦,發(fā)現(xiàn)實際結(jié)果并不是我們想要的垫言,鍵值對的參數(shù)跑到元組里面去了贰剥,那下面看一下正確的傳入方式:
t = (1, 2, 3)
def func(a, *args, **kwargs):? ? ?
????print('結(jié)果:')??????
????print(f'位置參數(shù):{a}')??????
????print(f'不定長元組參數(shù):{args}')??????
????print(f'不定長鍵值對參數(shù):{kwargs}')func(1, t, name='angst', age=18)?
結(jié)果:
位置參數(shù):1
不定長元組參數(shù):((1, 2, 3),)
不定長鍵值對參數(shù):{'name': 'angst', 'age': 18}
正確的參數(shù)傳入方式就是通過關(guān)鍵字參數(shù)的方式進(jìn)行傳入,這樣就達(dá)到了我們想要的目的筷频,但是蚌成,如果我就是想傳入一個字典類型的參數(shù)進(jìn)去怎么辦前痘?
d = {'name': 'amy', 'age': 18}
t = (1, 2, 3)def func(a, *args, **kwargs):
?????print('結(jié)果:')
?????print(f'位置參數(shù):{a}')
?????print(f'不定長元組參數(shù):{args}')
?????print(f'不定長鍵值對參數(shù):{kwargs}')func(1, t, **d)
結(jié)果:
位置參數(shù):1
不定長元組參數(shù):((1, 2, 3),)
不定長鍵值對參數(shù):{'name': 'amy', 'age': 18}
其實也是可以的,方法跟元組的類似担忧,參數(shù)在傳入的時候加上 ** 就行了芹缔。那么最后一個問題?怎么獲取對應(yīng)不定長參數(shù)的值呢瓶盛?
d = {'name': 'amy', 'age': 18}
t = (1, 2, 3)def func(a, *args, **kwargs):
????print('結(jié)果:')
????print(f'位置參數(shù):{a}')
????print(f'不定長元組第一個參數(shù):{args[0][0]}')
????print(f'不定長鍵值對名稱參數(shù):{kwargs.get("name")}')func(1, t, **d)
結(jié)果:
位置參數(shù):1
不定長元組第一個參數(shù):1
不定長鍵值對名稱參數(shù):amy
從上面的列子可以看出乖菱,其實獲取的并沒有什么不同,元組通過下標(biāo)獲取蓬网,字典通過Key獲取窒所。
匿名函數(shù)??Lambda?
python 使用 lambda 來創(chuàng)建匿名函數(shù)。所謂匿名帆锋,意即不再使用 def 語句這樣標(biāo)準(zhǔn)的形式定義一個函數(shù)吵取。簡單來說就是不用給函數(shù)定義名稱;
? ?> lambda 只是一個表達(dá)式锯厢,函數(shù)體比 def 簡單很多皮官。
? ? >lambda的主體是一個表達(dá)式,而不是一個代碼塊实辑。僅僅能在lambda表達(dá)式中封裝有限的邏輯進(jìn)去捺氢。
? ? >lambda 函數(shù)擁有自己的命名空間,且不能訪問自己參數(shù)列表之外或全局命名空間里的參數(shù)剪撬。
? ? >雖然lambda函數(shù)看起來只能寫一行摄乒,卻不等同于C或C++的內(nèi)聯(lián)函數(shù),后者的目的是調(diào)用小函數(shù)時不占用棧內(nèi)存從而增加運行效率
以上是 菜鳥教程 的解釋残黑,下面來看具體的示例:
def hello(name):
?????print(f'hello {name}')hello('Amy')
angst = lambda name: print(f'hello {name}')
print(angst)
結(jié)果輸出:
hello Amy
<function <lambda> at 0x0000026EE6F34048>
????一個是正常的 hello() 函數(shù)定義和調(diào)用馍佑,又定義了一個lambda 函數(shù)賦值給了變量 angst,兩個函數(shù)的實際功能其實是一直的,但是從上面輸出的結(jié)果來看 angst 出輸出的是一個函數(shù)對象在內(nèi)存的地址梨水;其實并沒有調(diào)用拭荤,只是打印了angst 函數(shù)變量而已,正確的調(diào)用方式其實跟正常的函數(shù)一樣疫诽,在變量后面加上一個()
def hello(name):
????print(f'hello {name}')hello('Amy')
angst = lambda name: print(f'hello {name}')
angst('angst')
結(jié)果輸出:
hello Amy
hello angst
? ? 從上面可以看出舅世,其實匿名函數(shù)從本質(zhì)上來說并沒有不同,只是使用的場景稍微有些特許而已奇徒,由于lambda 函數(shù)沒有定義名稱雏亚,所有我們在定義的時候通過會賦值一個變量去引用,之前的變量一般都是一些參數(shù)類型逼龟,但是通過lambda的形式將函數(shù)賦值給變量评凝,通過變量調(diào)用該函數(shù)時需要帶上(),如果有參數(shù)就在()傳參即可追葡。lambda 的函數(shù)一般是用于比較簡單的函數(shù)表達(dá)腺律。lambda 函數(shù)還有一個特性就是自帶 return 關(guān)鍵字奕短,可以自動把結(jié)果返回給函數(shù)本身。
lambda:None匀钧;函數(shù)沒有輸入?yún)?shù)翎碑,輸出是 None?
lambda x, y: x+y;函數(shù)輸入是x和y之斯,輸出是它們的和
lambda *args: sum(args); 輸入是任意個數(shù)的參數(shù)日杈,輸出是它們的和(隱性要求是輸入?yún)?shù)必須能夠進(jìn)行加法運算)
lambda **kwargs: kwagrs.get(key);輸入是任意鍵值對參數(shù)佑刷,輸出是key 對應(yīng)的value
? ??根據(jù)這個lambda函數(shù)應(yīng)用場景的不同莉擒,可以將lambda函數(shù)的用法有以下幾種 參考博客:
? ? 1>.將lambda函數(shù)賦值給一個變量,通過這個變量間接調(diào)用該lambda函數(shù),調(diào)用時記得帶上()
????2>.將lambda函數(shù)賦值給其他函數(shù)瘫絮,從而將其他函數(shù)用該 lambda 函數(shù)進(jìn)行替換.
? ? ? ? 例:time.sleep=lambda x:None涨冀,在后續(xù)代碼中調(diào)用time庫的sleep函數(shù)將不會執(zhí)行原有的功能。執(zhí)行time.sleep(3)時麦萤,不會休眠3秒而是None
? ? 3>.將lambda函數(shù)作為其他函數(shù)的返回值鹿鳖,返回給調(diào)用者
????????例如:return lambda x, y: x+y 返回一個加法函數(shù)。lambda函數(shù)實際上是定義在某個函數(shù)內(nèi)部的函數(shù)壮莹,稱之為嵌套函數(shù)翅帜,或者內(nèi)部函數(shù)。對應(yīng)的命满,將包含嵌套函數(shù)的函數(shù)稱之為外部函數(shù)涝滴。內(nèi)部函數(shù)能夠訪問外部函數(shù)的局部變量,這個特性是閉包(Closure)編程的基礎(chǔ)胶台,在后面的高級教程裝飾器中會用到狭莱,這里就不描述具體的用法了,后續(xù)可以關(guān)注我的博客概作,有專門對陣裝飾器的用法講解腋妙。
????4>.將lambda函數(shù)作為參數(shù)傳遞給其他函數(shù)
? ? ? ? 例:部分Python內(nèi)置函數(shù)接收函數(shù)作為參數(shù)。map函數(shù):lambda函數(shù)用于指定對列表中每一個元素的共同操作讯榕。如:map(lambda x: x+1, [1, 2,3])將列表[1, 2, ????????3]中的元素分別加1骤素,其結(jié)果[2, 3, 4]
????lambda的使用一直存在一些爭議,lambda 函數(shù)的好處和局限都很明顯愚屁,到底要不要使用和什么使用需要自我實踐了济竹,只要在合理的時候使用合理的操作才是最合理的。
以上就是匿名函數(shù)的一些常用操作霎槐,當(dāng)然還有更多的高級用法送浊,有興趣的同學(xué)可以自行查閱資料。如果有疑問也可以給我留言丘跌。