Python利用*與**進(jìn)行解包的完整教學(xué)
學(xué)習(xí)筆記:?jiǎn)涡翘?hào) * 展開列表/元組為位置參數(shù),雙星號(hào) ** 展開字典為關(guān)鍵字參數(shù)。
前言
在 Python 函數(shù)調(diào)用里,* 和 ** 都用來(lái) 「解包」——把容器里的元素拆開,傳給函數(shù)。
| 符號(hào) | 解包對(duì)象 | 變成 |
|---|---|---|
* | 列表、元組等序列 | 位置參數(shù) func(1, 2, 3) |
** | 字典 | 關(guān)鍵字參數(shù) func(a=1, b=2) |
記憶:一個(gè)星號(hào)管位置,兩個(gè)星號(hào)管關(guān)鍵字。
一、單星號(hào)*— 展開序列
1.1 調(diào)用函數(shù)時(shí):*展開列表/元組
def greet(name, age, city):
print(f"{name}, {age}歲, 來(lái)自{city}")
args = ["Alice", 20, "Beijing"]
greet(*args)
# 等價(jià)于 greet("Alice", 20, "Beijing")
*args 把列表里的元素按順序當(dāng)作位置參數(shù)傳入。
元組也一樣:
point = (10, 20)
def draw(x, y):
print(x, y)
draw(*point) # draw(10, 20)
1.2 和普通參數(shù)混用
def foo(a, b, c):
print(a, b, c)
foo(1, *[2, 3]) # foo(1, 2, 3)
foo(*[1, 2], 3) # ? 語(yǔ)法錯(cuò)誤,* 解包段必須在最后或單獨(dú)使用
foo(1, *[], 3) # ? 同上
正確混用:
rest = [2, 3] foo(1, *rest) # ? a=1, b=2, c=3
1.3 定義函數(shù)時(shí):*args收集多余位置參數(shù)
def foo(*args):
print(args)
print(type(args))
foo(1, 2, 3)
# (1, 2, 3)
# <class 'tuple'>
| 場(chǎng)景 | * 的作用 |
|---|---|
調(diào)用時(shí) func(*[1,2,3]) | 把序列 拆開 傳入 |
定義時(shí) def f(*args) | 把多出來(lái)的位置參數(shù) 收進(jìn) 元組 |
1.4 解包其他序列
nums = range(1, 4) # range 對(duì)象
list(*nums) # ? range 不能直接 * 給 list()
print(*nums) # ? print(1, 2, 3)
def total(a, b, c):
return a + b + c
total(*[10, 20, 30]) # 60
二、雙星號(hào)**— 展開字典
2.1 調(diào)用函數(shù)時(shí):**展開 dict
def greet(name, age):
print(f"name={name}, age={age}")
info = {"name": "Alice", "age": 20}
greet(**info)
# 等價(jià)于 greet(name="Alice", age=20)
**info 把 dict 的每個(gè) key: value 變成 key=value 關(guān)鍵字參數(shù)。
2.2 定義函數(shù)時(shí):**kwargs收集多余關(guān)鍵字參數(shù)
def foo(**kwargs):
print(kwargs)
foo(a=1, b=2)
# {'a': 1, 'b': 2}
| 場(chǎng)景 | ** 的作用 |
|---|---|
調(diào)用時(shí) func(**d) | 把 dict 拆開 傳入 |
定義時(shí) def f(**kwargs) | 把關(guān)鍵字參數(shù) 收進(jìn) dict |
2.3 項(xiàng)目里的真實(shí)用法
filtered = {"max_step_num": 5}
cls(**filtered)
# 等價(jià)于 Configuration(max_step_num=5)
完整鏈條(src/config/configuration.py):
return cls(**{k: v for k, v in values.items() if v})
- 字典推導(dǎo)式 → 過(guò)濾得到有效配置
**→ 展開成Configuration(字段=值, ...)- 未出現(xiàn)的字段 → 用 dataclass 默認(rèn)值
三、*和**一起用
3.1 定義函數(shù):*args+**kwargs
def foo(a, b, *args, **kwargs):
print("a, b =", a, b)
print("args =", args)
print("kwargs=", kwargs)
foo(1, 2, 3, 4, x=10, y=20)
# a, b = 1 2
# args = (3, 4)
# kwargs= {'x': 10, 'y': 20}
a, b:前兩個(gè)位置參數(shù)*args:多出來(lái)的位置參數(shù) → 元組**kwargs:所有關(guān)鍵字參數(shù) → 字典
3.2 調(diào)用函數(shù):同時(shí)解包
def foo(a, b, c, x, y):
print(a, b, c, x, y)
pos = [3, 4]
kw = {"x": 10, "y": 20}
foo(1, 2, *pos, **kw)
# foo(1, 2, 3, 4, x=10, y=20)
# 輸出: 1 2 3 4 10 20
順序規(guī)則(調(diào)用時(shí)):
位置參數(shù) → *解包序列 → 關(guān)鍵字參數(shù) → **解包字典
3.3 強(qiáng)制關(guān)鍵字參數(shù)(Python 3+)
定義里單獨(dú)一個(gè) * 表示:后面的參數(shù)必須用關(guān)鍵字傳。
def connect(host, port, *, timeout=30, ssl=True):
...
connect("localhost", 3306, timeout=60) # ?
connect("localhost", 3306, 60) # ? timeout 必須用 timeout=60
你們項(xiàng)目的 @dataclass(kw_only=True) 也是類似思路:創(chuàng)建對(duì)象時(shí)必須寫 Configuration(max_step_num=3)。
四、*/**的其他用法(補(bǔ)充)
4.1 合并列表 / 元組
a = [1, 2] b = [3, 4] c = [*a, *b] # [1, 2, 3, 4]
4.2 合并字典
a = {"x": 1}
b = {"y": 2}
c = {**a, **b} # {"x": 1, "y": 2}
b = {"x": 99}
{**a, **b} # {"x": 99} 后面的覆蓋前面的
4.3 函數(shù)傳參轉(zhuǎn)發(fā)(包裝器常見寫法)
def wrapper(*args, **kwargs):
print("調(diào)用前")
result = original_func(*args, **kwargs) # 原樣轉(zhuǎn)發(fā)
print("調(diào)用后")
return result
五、*vs**對(duì)照表
單星號(hào) * | 雙星號(hào) ** | |
|---|---|---|
| 解包對(duì)象 | list、tuple、range 等序列 | dict |
| 調(diào)用時(shí)變成 | 位置參數(shù) | 關(guān)鍵字參數(shù) |
| 定義時(shí)收集 | *args → tuple | **kwargs → dict |
| 典型例子 | func(*[1, 2, 3]) | func(**{"a": 1}) |
| 元素要求 | 按順序?qū)?yīng)參數(shù) | key 必須是合法參數(shù)名 |
六、常見誤區(qū)
誤區(qū) 1:參數(shù)個(gè)數(shù)對(duì)不上
def foo(a, b):
pass
foo(*[1, 2, 3]) # ? TypeError: too many arguments
foo(**{"a": 1}) # ? TypeError: missing b
誤區(qū) 2:**的 key 不是合法標(biāo)識(shí)符
foo(**{"max-step": 5}) # ? key 帶橫線,不能當(dāng)參數(shù)名
foo(**{"max_step_num": 5}) # ?
誤區(qū) 3:重復(fù)傳參
def foo(a, b):
pass
foo(1, *[2, 3]) # ?
foo(1, b=2, *[3]) # ? b 傳了兩次
foo(1, **{"a": 99}) # ? a 傳了兩次
誤區(qū) 4:混淆「解包」和「乘法」
2 * 3 # 乘法 → 6 func(*[2, 3]) # 解包 → 傳入兩個(gè)參數(shù) 2 和 3
上下文不同:在函數(shù)調(diào)用或定義參數(shù)列表里,* / ** 是解包;在表達(dá)式里是運(yùn)算。
七、小練習(xí)
# 練習(xí) 1:用 * 解包
def add(a, b, c):
return a + b + c
print(add(*[1, 2, 3])) # 6
# 練習(xí) 2:用 ** 解包
def profile(name, age):
return f"{name}-{age}"
print(profile(**{"name": "Tom", "age": 18})) # Tom-18
# 練習(xí) 3:模擬項(xiàng)目
def fake_config(**kwargs):
print(kwargs)
fake_config(**{"max_step_num": 5, "locale": "zh-CN"})
八、小結(jié)
foo(*[1, 2, 3]) # 位置:foo(1, 2, 3)
foo(**{"a": 1, "b": 2}) # 關(guān)鍵字:foo(a=1, b=2)
cls(**{"max_step_num": 5}) # Configuration(max_step_num=5)
| 記住 | |
|---|---|
* | 拆 序列 → 位置參數(shù) |
** | 拆 字典 → 關(guān)鍵字參數(shù) |
| 調(diào)用時(shí) | 把容器 展開 傳進(jìn)去 |
定義時(shí) *args / **kwargs | 把多出來(lái)的參數(shù) 收進(jìn) 容器 |
到此這篇關(guān)于Python利用*與**進(jìn)行解包的完整教學(xué)的文章就介紹到這了,更多相關(guān)Python解包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python getpass實(shí)現(xiàn)密文實(shí)例詳解
這篇文章主要介紹了python getpass實(shí)現(xiàn)密文實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
python驗(yàn)證碼識(shí)別教程之滑動(dòng)驗(yàn)證碼
這篇文章主要給大家介紹了關(guān)于python驗(yàn)證碼識(shí)別教程之滑動(dòng)驗(yàn)證碼的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06
解決python問(wèn)題 Traceback (most recent call&n
這篇文章主要介紹了解決python問(wèn)題 Traceback (most recent call last),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Python中的random.uniform()函數(shù)教程與實(shí)例解析
今天小編就為大家分享一篇關(guān)于Python中的random.uniform()函數(shù)教程與實(shí)例解析,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
Python數(shù)據(jù)處理pandas讀寫操作IO工具CSV解析
這篇文章主要為大家介紹了Python?pandas數(shù)據(jù)讀寫操作IO工具之CSV使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
簡(jiǎn)單了解python gevent 協(xié)程使用及作用
這篇文章主要介紹了簡(jiǎn)單了解python gevent 協(xié)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
Pandas?DataFrame數(shù)據(jù)修改值的方法
本文主要介紹了Pandas?DataFrame修改值,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Python利用GeoPandas打造一個(gè)交互式中國(guó)地圖選擇器
在數(shù)據(jù)分析和可視化領(lǐng)域,地圖是展示地理信息的強(qiáng)大工具,被將使用Python、wxPython 和 GeoPandas 構(gòu)建的交互式中國(guó)地圖行政區(qū)劃選擇器,感興趣的可以了解下2025-08-08
在windows下使用python進(jìn)行串口通訊的方法
今天小編就為大家分享一篇在windows下使用python進(jìn)行串口通訊的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07

