一篇文章徹底搞懂Python魔法參數args和kwargs(通俗易懂)
今天,咱就來聊聊 Python 函數參數中的兩個 “魔法參數”——*args 和 **kwargs,它們能讓你的函數變得超級靈活,輕松應對各種復雜情況。不過對于新接觸Python的同學來說是一個不好理解的概念,Up第一次接觸也覺得過于靈活而不好理解。今天,Up嘗試用通俗易懂的語言來說清楚。
提前劃重點
- 什么是位置參數和關鍵字參數?
- *args本質是個元組
- **kwargs本質是個字典
- 如何結合使用*args和**kwargs
- 在裝飾器中使用 * args 和 **kwargs
位置參數和關鍵字參數
在深入了解 * args 和 **kwargs 之前,咱們得先熟悉一下 Python 函數參數中的兩個 “常規(guī)軍”—— 位置參數和關鍵字參數,它們可是函數傳參的基礎。
位置參數,顧名思義,就是在調用函數時,按照參數的順序依次傳遞給函數的參數,實參的位置和形參的位置要一一對應,就像排隊領東西,先來的先領,順序不能亂。比如說,咱們定義一個計算兩數之和的函數:
def add_numbers(a, b): return a + b
這里的 a 和 b 就是位置參數,當我們調用這個函數時,就得按照順序傳入兩個數:
result = add_numbers(3, 5) print(result)
在這個例子中, 3 會被賦值給 a, 5 會被賦值給 b,函數返回它們的和 8。
而關鍵字參數呢,就靈活多了。它是指在調用函數時,通過指定參數名來為參數賦值,這樣就不用拘泥于參數的位置順序,讓代碼更加清晰易讀。還是用剛才的加法函數舉例,我們可以這樣調用:
result = add_numbers(a=3, b=5)
甚至還可以交換順序:
result = add_numbers(b=5, a=3)
不管順序如何,只要參數名寫對,就能準確地把值賦給對應的形參,是不是很方便?這在函數參數較多的時候特別有用,能讓你一眼就看明白每個參數的含義。
另外,位置參數和關鍵字參數還能混合使用,不過要記住一條規(guī)則:位置參數必須在關鍵字參數之前。比如:
def greet(name, message): print(f"{message}, {name}!") greet("小明", message="你好")
這樣寫沒問題,但要是寫成 greet(message=“你好”, “小明”),Python 就會報錯,因為違反了位置參數在前的原則。
*args 本質是個元組
*args 就像是一個 “參數收集器”,它能夠把函數調用時多余的位置參數一股腦兒地收集起來,然后打包成一個元組(tuple)。這里要注意哦,名字不一定非得是args,寫成numbers、values 之類的都沒問題,關鍵是那個星號,它就像是一個 “魔法標記”,告訴 Python:“嘿,我要收集多余的位置參數啦!”
咱們來看個例子,假如你要寫一個函數,計算任意多個數字的總和,你不確定用戶會輸入幾個數字,這時候 * args 就能大顯身手了:
def sum_numbers(*args): total = 0 for number in args: total += number return total
在這個函數里,*args 就像一個口袋,不管你傳入多少個位置參數,它都能接住,然后把這些參數變成一個元組。比如,咱們這樣調用這個函數:
result = sum_numbers(1, 2, 3, 4, 5) print(result)
這里傳入的 1、2、3、4、5 就會被 * args 收集起來,變成元組 (1, 2, 3, 4, 5),然后在函數內部,通過循環(huán)遍歷這個元組,把每個數字相加,最終得到總和 15。
**kwargs 本質是個字典
講完了*args,咱們再來看看另一位主角 ——**kwargs。它同樣有個神奇的 “魔法標記”—— 兩個星號**,有了它,函數就能把調用時傳入的任意數量的關鍵字參數統(tǒng)統(tǒng)收集起來,整理成一個字典(dict)。和 * args 一樣,名字不固定,寫成 **params、**options 之類的都行,關鍵是那兩個星號。
咱們來看個例子,假如你要寫一個函數,用來展示一個人的詳細信息,你不知道用戶會提供哪些具體信息,這時候 **kwargs 就能派上用場啦:
def show_person_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}")
在這個函數里,**kwargs 就像一個萬能的信息收納盒,不管你傳入多少個關鍵字參數,它都能接住,然后把這些參數變成一個字典。比如,咱們這樣調用這個函數:
show_person_info(name="小明", age=20, city="北京")
這里傳入的 name=“小明”、age=20、city=“北京” 就會被 **kwargs 收集起來,變成字典 {“name”: “小明”, “age”: 20, “city”: “北京”},然后在函數內部,通過遍歷這個字典,把每個鍵值對都打印出來,展示出這個人的詳細信息。
從函數定義的角度來看,**kwargs 也必須放在參數列表的最后面,這是為了讓 Python 解釋器能正確地識別參數。要是你把它放在前面,后面的參數就可能會被誤認成關鍵字參數,導致程序出錯。
如何結合使用 * args 和 **kwargs
了解了 * args 和 **kwargs 各自的特點,接下來咱們看看怎么把它們結合起來使用.
在實際編程中,有很多場景需要同時處理位置參數和關鍵字參數,而且數量還不確定。比如說,你要寫一個函數來記錄日志信息,日志可能包含一些固定的格式信息(類似關鍵字參數),還可能有一些額外的描述信息(類似位置參數),這時候 * args 和 **kwargs 就能完美配合。
咱們來看個例子:
def log_message(message_type, *args, **kwargs): print(f"[{message_type}]") for arg in args: print(arg) for key, value in kwargs.items(): print(f"{key}: {value}")
在這個 log_message 函數中, message_type 是一個固定的位置參數,用來指定日志的類型,比如 “ERROR”、“INFO” 之類的。而 *args 用來接收一些額外的描述信息,**kwargs 則用來接收一些帶有特定名稱的詳細信息,像日志發(fā)生的時間、代碼行數等。
咱們這樣調用這個函數:
log_message("INFO", "程序啟動成功", time="2023-09-15 10:00:00", line_number=100)
這里,“程序啟動成功” 會被args 收集,變成元組 (“程序啟動成功”,),而 time=“2023-09-15 10:00:00” 和 line_number=100 會被**kwargs 收集,變成字典 {“time”: “2023-09-15 10:00:00”, “line_number”: 100}。函數內部先打印日志類型 “INFO”,接著遍歷*args 打印額外描述,再遍歷 **kwargs 打印詳細信息,輸出就會像這樣:
[INFO] 程序啟動成功 time: 2023-09-15 10:00:00 line_number: 100
在裝飾器中使用 * args 和 **kwargs
聊完了 * args 和 **kwargs 的基本用法,咱再來看看它們在裝飾器里如何使用!
對于裝飾器不太熟悉的小伙伴,可以看一下Up上期的文章哦!
那*args 和 **kwargs 在裝飾器里起什么作用呢?想象一下,如果被裝飾的函數可能接收不定數量的參數,就像咱們之前講的*args 和**kwargs 的用法,這時候裝飾器里的內部函數就得用 *args 和**kwargs 來接收這些參數,然后原封不動地傳給原函數,否則參數就傳遞不進去,會導致報錯。
咱們來看個例子,假設你要寫一個裝飾器,用來記錄函數的執(zhí)行時間,不管這個函數接收幾個參數,都能正常工作:
import time def timeit(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} 函數執(zhí)行時間: {end_time - start_time} 秒") return result return wrapper @timeit def add_numbers(*args): return sum(args) @timeit def show_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}")
在這個例子中, timeit 是裝飾器函數,它的內部函數 wrapper 使用 * args 和 **kwargs 接收任意數量的參數,然后把這些參數傳給原函數 func,不管是 add_numbers 函數接收不定數量的位置參數,還是 show_info 函數接收不定數量的關鍵字參數,都能被 wrapper 函數正確接收并傳遞,同時還能記錄下函數的執(zhí)行時間。比如,咱們調用 add_numbers(1, 2, 3, 4, 5),會先記錄開始時間,執(zhí)行 add_numbers 函數計算總和,再記錄結束時間,打印出函數執(zhí)行時間,最后返回總和;調用 show_info(name=“小明”, age=20) 也是類似,先記錄時間,打印信息,再返回 None(因為 show_info 函數沒有返回值)。
要是裝飾器里的內部函數不使用 * args 和 *kwargs,而是寫死了固定的參數,那這個裝飾器就只能用于特定參數數量和類型的函數,靈活性就大打折扣了。比如說,你把 wrapper 函數寫成 def wrapper(a, b),那它就只能裝飾接收兩個位置參數的函數,要是用來裝飾 add_numbers(args) 這種不定參數的函數,就會報錯,提示參數數量不匹配。
所以說,args 和 **kwargs 在裝飾器里就像是兩座 “橋梁”,讓裝飾器能夠無縫對接各種不同參數的函數,極大地拓展了裝飾器的應用范圍,讓你的代碼復用性更強,不管是簡單的函數增強,還是復雜的框架開發(fā),都離不開它們的身影,掌握了在裝飾器中使用args 和 **kwargs 的技巧,你就能在 Python 編程的世界里更加游刃有余啦!
總結
到此這篇關于Python魔法參數args和kwargs的文章就介紹到這了,更多相關Python魔法參數args和kwargs內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python解析庫Beautiful?Soup安裝的詳細步驟
Beautiful?Soup是python的一個庫,最主要的功能是從網頁抓取數據,下面這篇文章主要給大家介紹了關于python解析庫Beautiful?Soup安裝的詳細步驟,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-04-04Python實現(xiàn)讀取txt文件并轉換為excel的方法示例
這篇文章主要介紹了Python實現(xiàn)讀取txt文件并轉換為excel的方法,涉及Python針對txt文件的讀取及Excel格式文件生成相關操作技巧,需要的朋友可以參考下2018-05-05Python OpenCV基于霍夫圈變換算法檢測圖像中的圓形
這篇文章主要介紹了通過霍夫圈變換算法檢測圖像中的圓形,文中用到的函數為cv2.HoughCircles(),該函數可以很好地檢測圓心。感興趣的小伙伴可以了解一下2021-12-12Python 隨機生成測試數據的模塊:faker基本使用方法詳解
這篇文章主要介紹了Python 隨機生成測試數據的模塊:faker基本使用方法,結合實例形式詳細分析了Python 隨機生成測試數據的模塊faker基本功能、原理、使用方法及操作注意事項,需要的朋友可以參考下2020-04-04輕松掌握python的dataclass讓你的代碼更簡潔優(yōu)雅
本文總結了幾個我在使用Python的dataclass時常用的技巧,dataclass裝飾器可以幫助我們簡化數據類的定義過程,包括設置默認值、隱藏敏感信息、設置只讀對象以及將其轉化為元組和字典,通過使用dataclass,我們可以更高效地進行數據分析和處理,感興趣的朋友跟隨小編一起看看吧2025-01-01