2009-08-14 85 views
14

我需要一個python 3.1深度更新函數的字典(一個函數,將遞歸更新父字典內的子字典)。Python和字典像對象

但我想,在將來,我的功能可能不得不處理像字典但不是字典的對象。此外,我想避免使用isinstancetype(因爲他們被認爲是不好的,因爲我幾乎可以在每個Pythonista的博客上閱讀)。

但是鴨子打字是Python的哲學的一部分,所以我怎麼能檢查一個對象是字典樣?

謝謝!

編輯:感謝所有的答案。以防萬一,我編碼的功能可以在這個地方找到:http://blog.cafeaumiel.com/public/python/dict_deep_update.py

+0

一向走毯語句在博客上用一粒鹽。我是鴨子打字的忠實粉絲,並且「比請求寬容更容易」的方法,但請參閱下面關於ABC的PEP 3119關於ABC的更多細微討論:http://www.python.org/dev/ peps/pep-3119/ – Anon 2009-08-14 14:34:41

+0

[相關問題](http://stackoverflow.com/questions/8601268/python-class-that-acts-as-mapping-for-unpacking) - 你可以測試提到的存在方法。 – jvdm 2016-01-21 17:36:18

回答

15

退房集合模塊中的(在3.X新)抽象基類(ABC的):

http://docs.python.org/3.1/library/collections.html

我將考慮對映射isinstance檢查如以下:

>>> import collections 
>>> isinstance({},collections.Mapping) 
True 

然後,如果你製作屬於自己的類字典的類,可以製作藏品。搭建其基礎之一。

另一條路線試圖捕捉字典操作的任何異常,但是對於您所談論的遞歸,我寧願首先檢查基本類型,而不是處理找出哪些字典或子字典或其他字典成員是否在那裏拋出異常。

編輯添加:檢查映射ABC而不是反對dict的好處是,同樣的測試可以用於類似字典的類,無論它們是否爲字典子類,所以它更靈活,以防萬一。

+0

絕對正確:ABC可以讓你「針對界面編程而不是實現」,就像Gof4呼籲你的! - ) – 2009-08-14 14:29:50

+0

你的方式做得很好。但是,什麼是Gof4? – thomas 2009-08-14 14:39:53

+1

Gof4是「四人幫」的縮寫,這是本書的作者通常所稱的,因爲它比說出所有的名字更容易:http://www.amazon.com/Design-Patterns-Object-Oriented-Addison -Wesley-Professional/dp/0201633612/ref = sr_1_1?ie = UTF8&qid = 1250260861&sr = 8-1 – Anon 2009-08-14 14:42:06

2

使用isinstance,它沒有什麼不對,並且它通常用於需要遞歸的代碼中。

如果按照字典的形式指示對象的類繼承dictisinstance也將返回True

>>> class A(dict): 
    pass 

>>> a = A() 
>>> isinstance(a, dict) 
True 
+2

fac是我不想針對* dict *類的代碼,但是針對它的接口:) – thomas 2009-08-14 14:41:15

1

鴨子打字就是你做你想做什麼的地方,如果你的物品沒有按照你預期的方式行事,那就處理掉落。

你想檢查是否有類似字典,並更新它,如果是的話,對不對?只要調用對象的更新方法,並處理如果沒有這種方法就會得到的異常。

當然,如果處理具有更新方法的自定義類對象,這完全是另一回事 - 我不太清楚該如何處理。

+0

我不使用* dict *類的更新方法。相反,我手動走字典,當一個值是一個字典像對象時,我嘗試遞歸調用我的函數,以便更新它。 – thomas 2009-08-14 14:44:21

0

如果您還必須處理類似字典但不是字典子類的自定義類,則可以使用getattr獲取所需的功能。

# loop 
# ... more code 
someObject = getObject(..) 
try: 
    getattr(someObject, "update")("someValue") 
except AttributeError: 
    # Wasn't a type we can handle 
1

那麼,爲了遞歸地更新字典,你必須調用'items'方法來迭代它。

因此,我建議,你只是做:

try : 
    for key, value in data.items() : 
     # recursive call 
except AttributeError : 
    # handling the trouble 
1

我喜歡來檢查「__setitem__」魔術方法......這是什麼讓foo的[「酒吧」] =巴茲行爲。

if getattr(obj, '__setattr__'): 
    obj[key] = val 

這裏是python 2.7 docs