請參閱下面的f
。函數f
有兩個參數,一個叫做name
的位置參數和一個關鍵字參數message
。它們是函數調用框架中的局部變量。
當你做f("John", **{"foo": "123", "message": "Hello World"})
,功能f
將解壓縮字典到本地變量通過其鍵/值對。最後你有三個本地變量:name
,foo=123
和message=Hello World
。
**kwargs
的目的,雙星號用於uknown關鍵字的參數。
進行對比:
def f(name, message=None):
if message:
return name + message
return name
在這裏,我要告訴用戶,如果你想打電話給f
,你可以通過關鍵字參數message
。如果有這樣的話,這是我唯一會接受和希望得到的唯一的克瓦格。如果你嘗試f("John", foo="Hello world")
,你會得到意想不到的關鍵字參數。
**kwargs
如果您事先不知道要接收哪些關鍵字參數(對調度到較低級別的函數/方法非常常見),那麼您可以使用它。
def f(name, message=None, **kwargs):
if message:
return name + message
return name
在第二個例子中,你可以做f("John", **{"foo": "Hello Foo"})
而省略message
。你也可以做f("John", **{"foo": "Hello Foo", "message": "Hello Message"})
。
- 我可以忽略它嗎?
如您所見,您可以忽略它。這裏f("John", **{"foo": "Hello Foo", "message": "Hello Message"})
我仍然只使用message
並忽略其他所有內容。
請勿使用**kwargs
,除非您需要對輸入不小心。
- 如果我的輸入是字典呢?
如果你的函數只是使用字典和修改字典,不使用individualida密鑰,那麼只需傳遞字典。沒有理由將字典項目變成變量。
但是這裏有兩個主要的用法**kwargs
。
假設我有一個班,我想在飛行中創建屬性。我可以使用setattr
來設置輸入的類屬性。
class Foo(object):
def __init__(**kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
如果我做Foo(**{"a": 1, "b": 2})
我會在最後Foo.a
和Foo.b
。
當你必須處理遺留代碼時,這特別有用。但是,有一個很大的安全問題。想象一下你擁有一個MongoDB實例,這是一個寫入數據庫的容器。想象一下,這個詞典是來自用戶的請求表單對象。用戶可以剷除任何東西,並且只需將它像這樣保存在數據庫中?這是一個安全漏洞。確保你驗證(使用循環)。
kwargs的第二個常見用法是,你不知道我所覆蓋的時間(它實際上是第一種常見的用法)。
是的,但是如果我確實知道這個參數肯定會是一個字典。我可以忽略它嗎? – zoujyjs
是的。查看我的答案或提供額外的上下文。 – CppLearner
我重新閱讀您的評論,您期待輸入是字典嗎?那麼我建議不要。但請閱讀我更新的帖子。 – CppLearner