2014-02-17 66 views
1
def accept(**kwargs): 
    pass 

如果我定義accept,我期望它通過傳遞一個參數是字典調用。所有詞典參數都需要星號嗎?應該所有字母參數在python裝飾星號

,如果我不喜歡的東西是什麼:

def accept(dict): 
    pass 

dict = {...} 
accept(dict) 

具體而言,我想實現的一類,它保持一個字典作爲一個容器update方法。就像dict.update方法一樣,它需要一個字典作爲參數並修改容器的內容。在這種特殊情況下,我應該使用kwargs嗎?

回答

1

請參閱下面的f。函數f有兩個參數,一個叫做name的位置參數和一個關鍵字參數message。它們是函數調用框架中的局部變量。

當你做f("John", **{"foo": "123", "message": "Hello World"}),功能f解壓縮字典到本地變量通過其鍵/值對。最後你有三個本地變量:name,foo=123message=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"})

  1. 我可以忽略它嗎?

如您所見,您可以忽略它。這裏f("John", **{"foo": "Hello Foo", "message": "Hello Message"})我仍然只使用message並忽略其他所有內容。

請勿使用**kwargs,除非您需要對輸入不小心。

  1. 如果我的輸入是字典呢?

如果你的函數只是使用字典和修改字典,不使用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.aFoo.b

當你必須處理遺留代碼時,這特別有用。但是,有一個很大的安全問題。想象一下你擁有一個MongoDB實例,這是一個寫入數據庫的容器。想象一下,這個詞典是來自用戶的請求表單對象。用戶可以剷除任何東西,並且只需將它像這樣保存在數據庫中?這是一個安全漏洞。確保你驗證(使用循環)。

kwargs的第二個常見用法是,你不知道我所覆蓋的時間(它實際上是第一種常見的用法)。

+0

是的,但是如果我確實知道這個參數肯定會是一個字典。我可以忽略它嗎? – zoujyjs

+0

是的。查看我的答案或提供額外的上下文。 – CppLearner

+0

我重新閱讀您的評論,您期待輸入是字典嗎?那麼我建議不要。但請閱讀我更新的帖子。 – CppLearner

2

**函數參數將所有關鍵字參數作爲字典收集。

>>> def accept(**kwargs): # isinstance(kwargs, dict) == True 
...  pass 
... 

使用Call關鍵字參數:

>>> accept(a=1, b=2) 

呼叫使用**操作:

>>> d = {'a': 1, 'b': 2} 
>>> accept(**d) 
>>> accept(d) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: accept() takes exactly 0 arguments (1 given) 

Python tutorial - Keyword argumentUnpacking Argument Lists

順便說一句,不要使用dict作爲變量名稱。它陰影內置函數/類型dict

+0

如果我忽略'**',我可以正確讀取參數。至於上面的例子,我打印字典的關鍵val對。 – zoujyjs

+0

@zoujyjs,對不起,但我不理解評論。 – falsetru

+0

看到我的更新,我的意思是沒有這個雙星號的功能運作良好。 – zoujyjs

1

如果你想通過一本字典爲輸入功能,你可以簡單地做這樣的

def my_function1(input_dict): 
    print input_dict 

d = {"Month": 1, "Year": 2} 

my_function1(d)  # {'Month': 1, 'Year': 2} 

這是直線前進。讓我們看看**kwargs方法。 kwargs代表關鍵字參數。所以,實際上你需要傳遞的參數鍵值對,這樣

def my_function2(**kwargs): 
    print kwargs 

my_function2(Month = 1, Year = 2) 

但是,如果你有一本字典,如果你想傳遞的參數my_function2,它可以與拆包完成,像這樣

my_function2(**d)