2016-07-25 69 views
0

有沒有辦法使用set和get語句來創建函數的字典,然後將它們用作set和get函數?使用__get__,__set__字典項?

class thing(object): 
    def __init__(self, thingy) 
     self.thingy = thingy 
    def __get__(self,instance,owner): 
     return thingy 
    def __set__(self,instance,value): 
     thingy += value 

theDict = {"bob":thing(5), "suzy":thing(2)} 

theDict["bob"] = 10 

希望的結果是,10進入設置功能,並增加了現有的5

print theDict["bob"] 
>>> 15 

實際的結果是,該詞典替換數值

print theDict["bob"] 
>>> 10 

入口爲什麼我不能製作像.. theDict [「bob」]。add(10) 是因爲它構建了一個現有的,已經很好的工作g函數使用set和get。我正在處理的案例是一個邊緣案例,對於爲這一案件進行工作而重新編程一切都沒有意義。

我需要一些手段來存儲此set/get thingy的實例,它可以訪問,但不會創建可能會破壞現有引用的某個深度層。

請不要詢問實際的代碼。它會花費大量的代碼來封裝問題。

+0

什麼鬼?不,'__get__'和'__set__'不能像那樣工作。如果你現有的設計是在描述符本身上存儲'thingy',而不是描述符附加到的類的對象,我會高度懷疑你現有的設計。 – user2357112

+0

我對這個問題也很困惑......我不明白'__get__'和'__set__'與你正在做什麼有關。我想你可以創建一個包裝類來覆蓋'__getitem__'和'__setitem__'來以任何你想要的方式更新委託字典。然而,如果沒有看到一些真實的代碼(或者至少是你真正想要完成的事情的最低限度的例子),那麼很難給出更多的建議...... – mgilson

+0

你有這個主要問題,你必須決定哪個對象負責您的自定義行爲。現在你在字典上執行動作('theDict [「bob」] = 10')在'theDict'中爲鍵'bob'指定10(正如你所看到的,這個描述甚至沒有提到先前存儲在所述鍵下的值) ,但期望利用'thing'中的自定義邏輯。如果自定義邏輯在'thing'中,請'thing'去做,不要問字典。如果你不能,重新考慮你的設計。 –

回答

1

你可以做,如果你(也)使用的是瞭解你的Thing類,並分別處理它的字典的專用版本:

class Thing(object): 
    def __init__(self, thingy): 
     self._thingy = thingy 
    def _get_thingy(self): 
     return self._thingy 
    def _set_thingy(self, value): 
     self._thingy += value 

    thingy = property(_get_thingy, _set_thingy, None, "I'm a 'thingy' property.") 

class ThingDict(dict): 
    def __getitem__(self, key): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      return dict.__getitem__(self, key).thingy 
     else: 
      return dict.__getitem__(self, key) 

    def __setitem__(self, key, value): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      dict.__getitem__(self, key).thingy = value 
     else: 
      dict.__setitem__(self, key, value) 


theDict = ThingDict({"bob": Thing(5), "suzy": Thing(2), "don": 42}) 

print(theDict["bob"]) # --> 5 
theDict["bob"] = 10 
print(theDict["bob"]) # --> 15 

# non-Thing value 
print(theDict["don"]) # --> 42 
theDict["don"] = 10 
print(theDict["don"]) # --> 10 
+0

這幾乎適用於我,但有一個例外。傳遞參數的數量。我放入字典的類使用傳遞給它的實例。這個字典方法似乎沒有通過該實例。這種方法有沒有辦法做到這一點? –

1

不,因爲要執行theDict["bob"] = 10,Python運行時不會調用任何前一個值爲theDict["bob"]的方法。這與myObject.mydescriptor = 10調用描述符設置器不同。

那麼,如果引用計數爲零,那麼也許它會在前一個值上調用__del__,但我們不要去那裏!

如果你想做這樣的事情,那麼你需要改變字典的工作方式,而不是內容。例如,你可以繼承dict(通常警告你寫了一個非Liskov替代的派生類是Evil,Bad和Wrong)。或者您可以從頭開始實施collections.MutableMapping的實例。但我不認爲有任何方法利用存儲在其中的特殊值來劫持dict的正常運行。

+0

+1對'collections.MutableMapping'建議。請參閱:[http://stackoverflow.com/a/3387975/6084928](http://stackoverflow.com/a/3387975/6084928) –

+0

@Lex:我認爲實現一個具體的'collections.MutableMapping'容器是過度殺傷 - 一個相對簡單的'dict'子類很好。請參閱[我的答案](http://stackoverflow.com/a/38574478/355230)。 – martineau

+0

公平點。您的解決方案更簡潔。 –