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
六、常見(jiàn)問(wèn)題與陷阱
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
- 避免過(guò)度使用,當(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模塊的配合使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08python+mysql實(shí)現(xiàn)個(gè)人論文管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python+mysql實(shí)現(xiàn)個(gè)人論文管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10Python+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ī)選擇,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11PyQt5 QTable插入圖片并動(dòng)態(tài)更新的實(shí)例
今天小編就為大家分享一篇PyQt5 QTable插入圖片并動(dòng)態(tài)更新的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法
今天小編就為大家分享一篇PyCharm鼠標(biāo)右鍵不顯示Run unittest的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11pycharm安裝教程(下載安裝以及設(shè)置中文界面)
這篇文章主要給大家介紹了關(guān)于pycharm安裝教程,文中包括下載安裝以及設(shè)置中文界面,PyCharm是一款Python IDE,其帶有一整套可以幫助用戶在使用Python語(yǔ)言開(kāi)發(fā)時(shí)提高其效率的工具,需要的朋友可以參考下2023-10-10