Python基础教程:默认参数和可变参数
1. 默認(rèn)參數(shù)
在函數(shù)定義時(shí)附加一個(gè)賦值運(yùn)算符(=)來為參數(shù)指定默認(rèn)參數(shù)值。必選參數(shù)在前,默認(rèn)參數(shù)在后,匹配時(shí)從左往右進(jìn)行匹配。
使用默認(rèn)參數(shù)有什么好處?最大的好處是能降低調(diào)用函數(shù)的難度。
def enroll(name, gender, age=6, city='Beijing'):print('name:', name)print('gender:', gender)print('age:', age)print('city:', city)enroll('Sarah', 'F') enroll('Bob', 'M', 7) # 從左往右匹配,故是age = 7 enroll('Adam', 'M', city='Tianjin') # 可以直接指定賦值的參數(shù)名默認(rèn)參數(shù)很有用,但使用不當(dāng),也會(huì)掉坑里。默認(rèn)參數(shù)有個(gè)最大的坑,演示如下:
# 你使用默認(rèn)參數(shù)調(diào)用時(shí)出現(xiàn)如下情況 print(add_end()) print(add_end()) # 再次調(diào)用時(shí)結(jié)果就不對(duì)了 print(add_end())""" output: ['END'] ['END', 'END'] ['END', 'END', 'END'] """原因如下:Python 函數(shù)在定義的時(shí)候,默認(rèn)參數(shù) L 的值就被計(jì)算出來了,即[],因?yàn)槟J(rèn)參數(shù) L 也是一個(gè)變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改
變了 L 的內(nèi)容,則下次調(diào)用時(shí),默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時(shí)的[]了。所以,定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象!
2. 可變參數(shù)
可變參數(shù)就是傳入的參數(shù)個(gè)數(shù)是可變的,可以是 1 個(gè)、2 個(gè)到任意個(gè),還可以是 0 個(gè)。有以下兩種參數(shù)形式:
1)*args:接收N個(gè)位置參數(shù),轉(zhuǎn)換成元組tuple形式。這個(gè)*號(hào)到底是做什么用的呢?
a. 打包參數(shù):當(dāng)*號(hào)出現(xiàn)在函數(shù)參數(shù)中時(shí),即遇到帶*號(hào)的形參,那么就會(huì)把還未分配出去的實(shí)參以元組形式打包(pack),分配給那個(gè)帶
''' Python學(xué)習(xí)交流,免費(fèi)公開課,免費(fèi)資料, 免費(fèi)答疑,系統(tǒng)學(xué)習(xí)加QQ群:579817333 ''' def foo1(*args):print(args) # 輸出 (1, 2, 3, 4, 5)def foo2(a, *args):print('a:', a) print('args:', args) # 輸出 (2, 3, 4, 5)foo1(1, 2, 3, 4, 5) # 1,2,3,4,5被打包分配給args foo2(1, 2, 3, 4, 5) # 1 配給 a, 2,3,4,5被打包分配給args這種打包參數(shù)的方法也可以使用在不確定元素個(gè)數(shù)的情況下的賦值,表述有點(diǎn)抽象,直接看個(gè)例子:
# 假如 record 后面都是電話號(hào)碼但是不知道有多少個(gè) record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212') name, email, *phone_numbers = record print(phone_numbers) # ['773-555-1212', '847-555-1212']# 最后一個(gè)元素會(huì)被 current 占用,其余均被打包 *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3] print(trailing) # [10, 8, 7, 1, 9, 5, 10]# 也可用在循環(huán)中 records = [('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4)] def do_foo(x, y):print('foo', x, y)def do_bar(s):print('bar', s)for tag, *args in records:if tag == 'foo':do_foo(*args) # 這里是拆包,可以看下面理解下elif tag == 'bar':do_bar(*args)b. 拆分參數(shù):當(dāng)*號(hào)出現(xiàn)在實(shí)參中時(shí),即傳入帶*號(hào)的實(shí)參,那么會(huì)把打包了的實(shí)參(元組或列表),拆分成單個(gè)的變量,依次賦值給函數(shù)的形參。
''' Python學(xué)習(xí)交流,免費(fèi)公開課,免費(fèi)資料, 免費(fèi)答疑,系統(tǒng)學(xué)習(xí)加QQ群:579817333 ''' def bar(a, b, c, d=10):print(a, b, c, d)bar(*[1, 2, 3])2)**kwargs:接收N個(gè)關(guān)鍵字參數(shù),轉(zhuǎn)換成字典dict形式。**號(hào)的作用與*號(hào)是一樣的,只是打包或拆分的形式不一樣:
a. 打包參數(shù):對(duì)于帶**號(hào)的形參,會(huì)把多個(gè)實(shí)參參數(shù)打包成字典。
def bar(**kw):print(kw) # 輸出:{'a': 1, 'b': 2, 'c': 3}bar(a=1, b=2, c=3)b. 拆分參數(shù):對(duì)于帶**號(hào)的實(shí)參,會(huì)把已經(jīng)打包的字典的鍵值拆成單個(gè),依次賦值給函數(shù)的形參。
def bar(a, b, c):print(a,b,c) # 輸出:1,2,3bar(**{'a': 1, 'b': 2, 'c': 3}) # 每個(gè)key必須和bar的形參名一致如果我們希望檢查是否有某個(gè)參數(shù),如 city 和 job,可以這樣:
def person(name, age, **kw):if 'city' in kw:# 有 city 參數(shù)passif 'job' in kw:# 有 job 參數(shù)passprint('name:', name, 'age:', age, 'other:', kw)extra = {'city': 'Beijing', 'job': 'Engineer'} person('Jack', 24, **extra)注:無論函數(shù)參數(shù)是怎么樣的,我們都可以通過拆分參數(shù)這種形式進(jìn)行賦值,看個(gè)例子:
args 和 kw 被拆分后會(huì)按順序賦值給 test 的形參。
''' Python學(xué)習(xí)交流,免費(fèi)公開課,免費(fèi)資料, 免費(fèi)答疑,系統(tǒng)學(xué)習(xí)加QQ群:579817333 ''' args = (1,2) kw = {}def test(a,b):print(a,b)test(*args, **kw) # 完全不必去管test的參數(shù)有幾個(gè)或者是怎樣的形式3. 只接受關(guān)鍵字參數(shù)
將強(qiáng)制關(guān)鍵字參數(shù)放到某個(gè) *參數(shù)或者單個(gè)*后面就能達(dá)到這種效果。比如:
def recv(maxsize, *, block):'Receives a message'passrecv(1024, True) # TypeError recv(1024, block=True) # Ok總結(jié)
以上是生活随笔為你收集整理的Python基础教程:默认参数和可变参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python中的defaultdict函
- 下一篇: Python基础教程:高阶函数和函数嵌套