前言
進階篇的語法,python 新手來說可以完全先不用碰,
(碰了可能有比較厲害,但更有可能觀念大亂),
大部分的功能只需要靠基礎篇的內容就能實現了!
建議會先把基礎的都學會再來看哦!
args, kwargs 是慣用名,使用時,我們不太會只講這個部分,會連前面的符號一起講
因此以下都請看作「*args」、「**kwargs」
小提示
因為開始講到比較細的東西,用詞上我會更小心一些,
注意以下 parameters 與 arguments 位置的差別,
雖然翻譯幾乎相同也很常混用就是…. 我自己之前也常講錯
def foo(parameters):
pass
foo(arguments)
args 與 kwargs
python 裡面我們傳參數 (arguments) 給 function 時,
我們更仔細的看,其實在 arguments 我們就可以預先指定給傳給特定的 key,
這個順序有個嚴格的排列,必須先 args 再 kwargs
- args: 位置參數 (不指定 key 的都必須先放在前面,且順序很重要)
- kwargs: key word (故意分開表示 kw) arguments 關鍵字參數,只要擺比 args 後面即可。
當我們指定 keywords, 我們就可以無視順序的傳入參數給 function,
但如果我們沒有指定,就是一律按照順序
args
思考問題
請問以下會印出什麼呢?(建議先想過再往下看,如果答對了基本上就已經理解囉!)
def my_function(*args):
for arg in args:
print(arg)
my_function(1, 2, 3, 4)
答案
我們所傳入所有的 args,其實如果是以 *args 的方式去接這些變數,就會依照順序。
(args 只是習慣,實際上可以替換成別的名稱)
kwargs
思考問題
請問以下會印出什麼呢?(建議先想過再往下看,如果答對了基本上就已經理解囉!)
def my_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
my_function(a=1, b=2, c=3)
答案
**kwargs: 可以讓我們以 dict 的方式把所有帶有 key 的變數儲存,
一樣 kwargs 只是慣用名,不一定要用這個名字。
同時出現的 args 與 kwargs
我們從上面先分別了解兩者的功能後,當一個 function 出現類似
def func(*args, **kwargs):
pass
表示「無論傳入任何的變數,這個 func 都能吃的進去」 (當然也先必須符合 args 在前, kwargs 在後的前提)
用途
從上面的敘述中,我們可以發現這種方式給予我們在撰寫 func 的時候有最大的彈性,
所以我們會使用與一些可能還不確定傳入內容,或本身就需要彈性的設計 (對外給客戶的 API …)
思考問題
請問以下會印出什麼呢?(建議先想過再往下看,如果答對了基本上就已經理解囉!)
def foo(*args, **kwargs):
print(type(args))
print(type(kwargs))
for ele in args:
print(ele)
for k, v in kwargs.items():
print(f"{k}: {v}")
foo(1, 2, 3, a=4, b=5, c=6)
答案
進階討論:關於「*」這個符號
「*」 在 python 裡面有 unpack (展開) tuple (list 也可以) 的意思
而兩個的「**」,是可以 unpack dict
最後我的理解是
我們可以直接把「*args」,傳入 func 後,扣掉符號所剩下的 「args」當成是 tuple (list),
而直接把「**kwargs」,傳入 func 後,扣掉符號所剩下的 「kwargs」當成是 dict
這是我目前認為最容易理解的方式了。
題外話的嘗試
所以也有以下的用法:
mylist = [1, 2, 3]
print(*mylist)
會印出 1 2 3 (針對每個元素各別印出),
這段程式碼可翻譯為 print(1, 2, 3)
而我們沒辦法同樣的印出 print(**mydict)
因為這段程式碼會被翻譯為 print(a=4, b=5, c=6),
而這種帶有 keyword 的 print 本來就不能印出東西來