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

