打包與解包
阿新 • • 發佈:2021-07-04
Python中的*號使用場景與區別
直白點的區別就是:函式呼叫時,*和都是解包,函式定義時是將傳過來的引數進行打包**
星號的使用場景有兩個
- 在【函式定義】和【函式呼叫】的時候使用
- 作為接收序列引數:a,*b=1,2,3,4
這裡主要講第一種
函式定義時.
- args: 接收傳遞過來的序列引用,讀取引用中的位置引數,【打包】成一個元祖,將引用指向args
- kwargs: 接收傳遞過來的字典引用,讀取引用中的關鍵字引數,【打包】成一個字典,將引用指向kwargs
注意:如果引數列表有*args,**kwargs,但是沒有接收到引數,那麼輸出args就是一個空元祖,kwargs是個空字典,當引數args只有一個時,那麼輸出的元祖就是(1,)後面有一個,代表是個元祖
函式呼叫時
- *args 和**kwargs:傳遞的是序列的引用,獲取引用中的值,然後作為實參傳遞
- 注意事項:由於是引用,會更改內部的值,如圖
場景1:函式定義與呼叫都不使用*號
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(tmp):
print(tmp)
print(*tmp) # 這裡面和上面一樣序列解包
f(a) # 直接傳列表引用作為引數
f(b) # 與函式外面保持一致
f(c) # 與函式外面保持一致
[1, 2, 3, 4] 1 2 3 4 (7, 8, 9, 10) 7 8 9 10 {'age': 18, 'name': 'vdx'} age name
提問:既然能直接定義一個變數接收序列的引用,為什麼還需要用*和**?
思考:雖然效果是一樣的,但是有些情況不是直接傳列表,而是單個單個的位置引數傳遞,比如fun(1,2,3)
場景2:函式定義時:使用*號
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(*tmp):
print(tmp)
print(*tmp)
f(a) # 直接傳列表引用作為引數,注意:函式能直接更改原件,如果想弄副本,加上*
f(b)
f(c)
(1, 2, 3, 4) 1 2 3 4 ((7, 8, 9, 10),) (7, 8, 9, 10) ({'age': 18, 'name': 'vdx'},) {'age': 18, 'name': 'vdx'}
場景3:函式定義時:使用*號
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(**tmp):
print(tmp)
f(**c) # 與函式外面保持一致
{'age': 18, 'name': 'vdx'}
提示:對字典使用*,能夠取出裡面的key
為什麼我們不能print(**kwargs),卻能print(*args)
不是說**不能解包,而是print不支援輸出關鍵字引數
區別歸納
1.之前賦值時,*可以用來接收多餘的物件值,那種用法與函式中的用法不一樣,切記混合使用,【一個是賦值時接收多餘的引數,一個是在函式中傳遞,接收多個值是使用】
例題:
# 二、請寫出下列程式碼的執行結果
def f(str1, *args, **kwargs):
print(str1, args, kwargs)
l = [1, 2, 3]
t = [4, 5, 6]
d = {"a": 7, "b": 8, "c": 9}
f(1, 2)
f(1, 2, 3, "python")
f("python", a=1, b=2, c=3)
f("python", l, d)
f("python", *t)
f('python', *l, **d)
f("python", q="winning", **d)
print('-' * 90)