2012-09-25 133 views
0

我有這個(Py2.7.2)字典值:暴露通過屬性

class MyClass(object): 
    def __init__(self, dict_values): 
     self.values = dict_values 
     self.changed_values = {} #this should track changes done to the values{} 
     .... 

我可以這樣使用它:

var = MyClass() 
var.values['age'] = 21 
var.changed_values['age'] = 21 

但我想用這樣的:

var.age = 21 
print var.changed_values #prints {'age':21} 

我懷疑我可以使用屬性來做到這一點,但如何?

UPDATE:

我不知道在設計時的字典內容。它僅在運行時纔會被知道。並且它可能不是空的

+1

'changed_values'有什麼用?它與「價值」有什麼不同?這是給你的嗎? – delnan

+0

簡單 - 我想看看究竟發生了什麼變化。是的,它可以用一個鍵列表代替,但這不是問題的關鍵。 – AlexVhr

+0

我的意思是,如何看待'values'的鍵不適合你?是否從'changed_values'中刪除了項目,並且'changed_values'中的值是否從'values'中的當前值改變了? – delnan

回答

1

您可以創建從字典繼承的類並重寫所需的功能

class D(dict): 
    def __init__(self): 
     self.changed_values = {} 
     self.__initialized = True 

    def __setitem__(self, key, value): 
     self.changed_values[key] = value 
     super(D, self).__setitem__(key, value) 

    def __getattr__(self, item): 
     """Maps values to attributes. 
     Only called if there *isn't* an attribute with this name 
     """ 
     try: 
      return self.__getitem__(item) 
     except KeyError: 
      raise AttributeError(item) 

    def __setattr__(self, item, value): 
     """Maps attributes to values. 
     Only if we are initialised 
     """ 
     if not self.__dict__.has_key('_D__initialized'): # this test allows attributes to be set in the __init__ method 
      return dict.__setattr__(self, item, value) 
     elif self.__dict__.has_key(item):  # any normal attributes are handled normally 
      dict.__setattr__(self, item, value) 
     else: 
      self.__setitem__(item, value) 

a = D() 
a['hi'] = 'hello' 
print a.hi 
print a.changed_values 

a.hi = 'wow' 
print a.hi 
print a.changed_values 

a.test = 'test1' 
print a.test 
print a.changed_values 

輸出

>>hello 
>>{'hi': 'hello'} 
>>wow 
>>{'hi': 'wow'} 
>>test1 
>>{'hi': 'wow', 'test': 'test1'} 
+0

這看起來很有趣,謝謝。但是,我想知道問題的最新部分是否可以簡化。 – AlexVhr

+0

使用這個實現,你可以像往常一樣更改字典內容(如第一個例子)或使用參數(如第三個例子)。因此,順便更新字典內容 –

+0

的時間和地點並不重要,如果你想擁有某種改變項目的日誌,我會建議使用一個元組列表,其中每個元組都是一對(核心價值)。這樣,如果值更改兩次,您可以看到它。另外,對於可以放置在該結構上的數據沒有限制,例如時間,舊值(對於撤消/重做功能而言是好的)... –

0

屬性(描述符,真的)只會在監視的屬性集有界時起作用。只需在描述符的__set__()方法中將新值刪除即可。

如果這組屬性是任意的或無界的,那麼您需要改寫MyClass.__setattr__()

+1

一段代碼會很好,謝謝 – AlexVhr

0

可以使用property()內置功能。

這優於重寫__getattr____setattr__,如解釋here

class MyClass: 

     def __init__(self): 
      self.values = {} 
      self.changed_values = {} 

     def set_age(nr): 
      self.values['age'] = nr 
      self.changed_values['age'] = nr 

     def get_age(): 
      return self.values['age'] 

     age = property(get_age,set_age) 
+0

但在這種情況下,我必須編寫「靜態」getter和setter。我想要做的是動態創建它們。 – AlexVhr