Python函數(shù)參數(shù)*args和**kwargs的區(qū)別與使用指南
一、基本概念與區(qū)別概述
1.1 *args(非關(guān)鍵字參數(shù)收集)
- 用于收集任意數(shù)量的位置參數(shù)
- 將傳入的位置參數(shù)打包成元組(tuple)
- 名稱不一定是
args,但約定俗成使用args(*才是關(guān)鍵)
1.2 **kwargs(關(guān)鍵字參數(shù)收集)
- 用于收集任意數(shù)量的關(guān)鍵字參數(shù)
- 將傳入的關(guān)鍵字參數(shù)打包成字典(dict)
- 名稱不一定是
kwargs,但約定俗成使用kwargs(**才是關(guān)鍵)
1.3 主要區(qū)別對(duì)比表
| 特性 | *args | **kwargs |
|---|---|---|
| 參數(shù)類型 | 收集位置參數(shù) | 收集關(guān)鍵字參數(shù) |
| 數(shù)據(jù)結(jié)構(gòu) | 打包為元組 | 打包為字典 |
| 符號(hào) | 單星號(hào)* | 雙星號(hào)** |
| 參數(shù)順序 | 必須出現(xiàn)在關(guān)鍵字參數(shù)之前 | 必須出現(xiàn)在*args之后 |
| 典型用途 | 處理可變數(shù)量的位置參數(shù) | 處理可變數(shù)量的關(guān)鍵字參數(shù) |
| 解包操作 | 可用于解包序列 | 可用于解包字典 |
二、深入理解*args
2.1 基本用法
def sum_numbers(*args):
total = 0
for num in args:
total += num
return total
print(sum_numbers(1, 2, 3)) # 輸出: 6
print(sum_numbers(1, 2, 3, 4, 5)) # 輸出: 15
2.2 工作原理
當(dāng)函數(shù)被調(diào)用時(shí):
- 所有未匹配的位置參數(shù)會(huì)被收集
- 這些參數(shù)被打包成一個(gè)元組
- 這個(gè)元組被賦值給
args(或你指定的參數(shù)名)
2.3 與其他參數(shù)配合使用
*args必須出現(xiàn)在位置參數(shù)之后,關(guān)鍵字參數(shù)之前:
def func(a, b, *args, option=True):
print(f"a: {a}, b: , args: {args}, option: {option}")
func(1, 2, 3, 4, 5, option=False)
# 輸出: a: 1, b: 2, args: (3, 4, 5), option: False
2.4 解包序列作為參數(shù)
*也可用于調(diào)用時(shí)解包序列:
numbers = [1, 2, 3, 4] print(sum_numbers(*numbers)) # 輸出: 10
三、深入理解**kwargs
3.1 基本用法
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="New York")
# 輸出:
# name: Alice
# age: 30
# city: New York
3.2 工作原理
當(dāng)函數(shù)被調(diào)用時(shí):
- 所有未匹配的關(guān)鍵字參數(shù)會(huì)被收集
- 這些參數(shù)被打包成一個(gè)字典
- 這個(gè)字典被賦值給
kwargs(或你指定的參數(shù)名)
3.3 與其他參數(shù)配合使用
**kwargs必須出現(xiàn)在所有參數(shù)之后:
def func(a, b, *args, option=True, **kwargs):
print(f"a: {a}, b: , args: {args}, option: {option}, kwargs: {kwargs}")
func(1, 2, 3, 4, 5, option=False, name="Alice", age=30)
# 輸出: a: 1, b: 2, args: (3, 4, 5), option: False, kwargs: {'name': 'Alice', 'age': 30}
3.4 解包字典作為參數(shù)
**也可用于調(diào)用時(shí)解包字典:
info = {"name": "Bob", "age": 25, "job": "Developer"}
print_info(**info)
# 輸出:
# name: Bob
# age: 25
# job: Developer
四、組合使用*args和**kwargs
4.1 完整參數(shù)順序規(guī)則
Python函數(shù)的參數(shù)順序必須遵循以下規(guī)則:
- 標(biāo)準(zhǔn)位置參數(shù)
*args(收集剩余位置參數(shù))- 關(guān)鍵字參數(shù)(有默認(rèn)值的參數(shù))
**kwargs(收集剩余關(guān)鍵字參數(shù))
def func(a, b, *args, c=10, d=20, **kwargs):
pass
4.2 實(shí)際示例
def process_data(name, *scores, report=False, **metadata):
print(f"Student: {name}")
print(f"Scores: {scores}")
print(f"Report: {'Yes' if report else 'No'}")
print("Metadata:")
for k, v in metadata.items():
print(f" {k}: {v}")
process_data("Alice", 85, 90, 78, report=True,
school="Harvard", year=2023, major="CS")
# 輸出:
# Student: Alice
# Scores: (85, 90, 78)
# Report: Yes
# Metadata:
# school: Harvard
# year: 2023
# major: CS
五、高級(jí)應(yīng)用場(chǎng)景
5.1 裝飾器中的參數(shù)傳遞
def debug(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned: {result}")
return result
return wrapper
@debug
def add(a, b):
return a + b
add(3, 5)
# 輸出:
# Calling add with args: (3, 5), kwargs: {}
# add returned: 8
5.2 子類化與super()調(diào)用
class Parent:
def __init__(self, name, *args, **kwargs):
self.name = name
print(f"Parent args: {args}, kwargs: {kwargs}")
class Child(Parent):
def __init__(self, age, *args, **kwargs):
super().__init__(*args, **kwargs)
self.age = age
child = Child(10, "Alice", school="Harvard")
# 輸出: Parent args: (), kwargs: {'school': 'Harvard'}
5.3 函數(shù)包裝與轉(zhuǎn)發(fā)
def call_with_log(func):
def wrapped(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapped
@call_with_log
def complex_operation(x, y, option=False):
return x * y if option else x + y
complex_operation(3, 4, option=True)
# 輸出:
# Calling complex_operation
# 返回: 12
六、常見問題與陷阱
6.1 參數(shù)順序錯(cuò)誤
# 錯(cuò)誤示例
def wrong_func(**kwargs, *args):
pass
# SyntaxError: invalid syntax
6.2 重復(fù)參數(shù)名
def func(a, *args, a=10): # 錯(cuò)誤: a重復(fù)
pass
# SyntaxError: duplicate argument 'a' in function definition
6.3 解包時(shí)的鍵沖突
def func(a, b, **kwargs):
print(a, b, kwargs)
params = {'a': 1, 'b': 2, 'c': 3}
func(**params) # 正常工作
# 輸出: 1 2 {'c': 3}
params = {'a': 1, 'b': 2, 'a': 100} # 重復(fù)鍵
func(**params) # 會(huì)使用最后的值
# 輸出: 100 2 {}
七、實(shí)際應(yīng)用案例
7.1 數(shù)據(jù)庫(kù)查詢構(gòu)建器
def build_query(table, *conditions, **filters):
query = f"SELECT * FROM {table}"
if conditions:
query += " WHERE " + " AND ".join(conditions)
if filters:
if not conditions:
query += " WHERE "
else:
query += " AND "
query += " AND ".join(f"{k} = {v!r}" for k, v in filters.items())
return query
print(build_query("users", "age > 18", "status = 'active'", country="USA"))
# 輸出: SELECT * FROM users WHERE age > 18 AND status = 'active' AND country = 'USA'
7.2 配置合并工具
def merge_configs(*configs, **overrides):
result = {}
for config in configs:
result.update(config)
result.update(overrides)
return result
default = {'color': 'red', 'size': 10}
user = {'size': 12, 'opacity': 0.8}
final = merge_configs(default, user, color='blue', speed='fast')
print(final)
# 輸出: {'color': 'blue', 'size': 12, 'opacity': 0.8, 'speed': 'fast'}
7.3 數(shù)學(xué)計(jì)算函數(shù)
def calculate(operation, *numbers, round_result=False, **options):
if operation == 'sum':
result = sum(numbers)
elif operation == 'product':
result = 1
for n in numbers:
result *= n
elif operation == 'average':
result = sum(numbers) / len(numbers) if numbers else 0
else:
raise ValueError("Unknown operation")
if round_result:
decimals = options.get('decimals', 2)
result = round(result, decimals)
return result
print(calculate('average', 1, 2, 3, 4, round_result=True))
# 輸出: 2.5
print(calculate('product', 2, 3, 4, round_result=True, decimals=1))
# 輸出: 24.0
八、總結(jié)與最佳實(shí)踐
8.1 何時(shí)使用*args
- 函數(shù)需要接受任意數(shù)量的位置參數(shù)時(shí)
- 包裝或轉(zhuǎn)發(fā)函數(shù)調(diào)用時(shí)
- 實(shí)現(xiàn)可變參數(shù)的數(shù)學(xué)運(yùn)算函數(shù)時(shí)
- 創(chuàng)建裝飾器時(shí)
8.2 何時(shí)使用**kwargs
- 函數(shù)需要接受任意數(shù)量的關(guān)鍵字參數(shù)時(shí)
- 實(shí)現(xiàn)配置選項(xiàng)或參數(shù)傳遞時(shí)
- 創(chuàng)建靈活的API或DSL時(shí)
- 子類化需要傳遞額外參數(shù)給父類時(shí)
8.3 最佳實(shí)踐建議
- 遵循參數(shù)順序規(guī)則:位置參數(shù) →
*args→ 關(guān)鍵字參數(shù) →**kwargs - 使用描述性的參數(shù)名而不僅僅是
args/kwargs(如*paths,**options) - 在文檔字符串中清楚地記錄接受的參數(shù)
- 考慮使用類型注解提高代碼可讀性:
def func(*args: int, **kwargs: str) -> float:
pass
- 避免過度使用,當(dāng)參數(shù)結(jié)構(gòu)明確時(shí),使用顯式參數(shù)更好
*args和**kwargs是Python靈活參數(shù)處理機(jī)制的核心,合理使用它們可以寫出更通用、更靈活的代碼,但同時(shí)也要注意不要濫用,以保持代碼的可讀性和可維護(hù)性。
以上就是Python函數(shù)參數(shù)*args和**kwargs區(qū)別與使用指南的詳細(xì)內(nèi)容,更多關(guān)于Python args和kwargs區(qū)別與使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Django發(fā)送郵件和itsdangerous模塊的配合使用解析
這篇文章主要介紹了Django發(fā)送郵件和itsdangerous模塊的配合使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
python+mysql實(shí)現(xiàn)個(gè)人論文管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python+mysql實(shí)現(xiàn)個(gè)人論文管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Python+OpenCV實(shí)現(xiàn)車牌字符分割和識(shí)別
這篇文章主要為大家詳細(xì)介紹了Python+OpenCV實(shí)現(xiàn)車牌字符分割和識(shí)別,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
如何在python中實(shí)現(xiàn)隨機(jī)選擇
這篇文章主要介紹了如何在python中實(shí)現(xiàn)隨機(jī)選擇,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
PyQt5 QTable插入圖片并動(dòng)態(tài)更新的實(shí)例
今天小編就為大家分享一篇PyQt5 QTable插入圖片并動(dòng)態(tài)更新的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06
PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法
今天小編就為大家分享一篇PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-11-11
pycharm安裝教程(下載安裝以及設(shè)置中文界面)
這篇文章主要給大家介紹了關(guān)于pycharm安裝教程,文中包括下載安裝以及設(shè)置中文界面,PyCharm是一款Python IDE,其帶有一整套可以幫助用戶在使用Python語言開發(fā)時(shí)提高其效率的工具,需要的朋友可以參考下2023-10-10

