2011-03-03 78 views
11

任何人都知道任何簡單的方法來跟蹤對python字典對象的更改嗎?我處於高層次上,所以我有幾個方法可以處理更改字典,如果字典更改,我想調用函數來基本執行Observer/Notify。Python Property Change Listener Pattern

class MyClass(object): 
    def update(self, item): 
     changed = False 

     if(self.my_dict.has_key(item.id)): 
      self.my_dict[item.id] = item 
      changed = True 

     if(changed): 
      self.notify() 

我試圖避免的是所有的跟蹤(設置布爾)代碼。希望有一個更簡單的方法來跟蹤變化。這是一個簡單的例子,但可能會有更復雜的邏輯,導致我不得不設置更改的標誌。

+0

'如果item.id在self.my_dict {self.my_dict [item.id] = item; self.notify()}'? (請原諒大括號和分號,但註釋吃線條) – delnan 2011-03-03 21:08:19

回答

12

您可以從dict類派生和任何更改添加的回調。這需要覆蓋任何更改字典的方法:

class NotifyDict(dict): 
    __slots__ = ["callback"] 
    def __init__(self, callback, *args, **kwargs): 
     self.callback = callback 
     dict.__init__(self, *args, **kwargs) 
    def _wrap(method): 
     def wrapper(self, *args, **kwargs): 
      result = method(self, *args, **kwargs) 
      self.callback() 
      return result 
     return wrapper 
    __delitem__ = _wrap(dict.__delitem__) 
    __setitem__ = _wrap(dict.__setitem__) 
    clear = _wrap(dict.clear) 
    pop = _wrap(dict.pop) 
    popitem = _wrap(dict.popitem) 
    setdefault = _wrap(dict.setdefault) 
    update = _wrap(dict.update) 
+0

這項工作,只需要注意參考類型... – Nix 2011-03-03 22:02:20

+0

@Nix - 小心如何,爲什麼?你能解釋一下嗎? – 2013-06-21 07:15:49

+3

@VijayVaradan這隻適用於一級屬性更改。所以,如果我有一個'obj'並且它有一個'dict'並且我修改了字典,那麼這個變化就不會被拾取。它只會選擇'obj.xyz',這是有道理的? – Nix 2013-06-21 14:39:10

0

子類dict並覆蓋__setitem__,確保在您的東西后面打電話dict.__setitem__以確保物品實際得到保存。

class Notifier(dict): 
    def __setitem__(self, key, value): 
     print 'Something is being set!' 
     dict.__setitem__(self, key, value) 
+0

然後你會如何使用'Notifier'?我有一個對象,我想知道什麼時候「self .__ member」值發生了變化?那麼'Notifier'封裝在那個對象中?你可以擴展如何使用它? – IAbstract 2016-02-13 13:10:48