2016-11-30 85 views
0

什麼是定義一個自定義按鍵功能類似於key參數list.sort,在一個collections.defaultdict使用的好辦法自定義鍵的功能?爲蟒蛇defaultdict

下面是一個例子使用案例:

import collections 

class Path(object): 
    def __init__(self, start, end, *other_features): 
     self._first = start 
     self._last = end 
     self._rest = other_features 
    def startpoint(self): 
     return self._first 
    def endpoint(self): 
     return self._last 
    # Maybe it has __eq__ and __hash__, maybe not 

paths = [... a list of Path objects ...] 

by_endpoint = collections.defaultdict(list) 
for p in people: 
    by_last_name[p.endpoint()].append(p) 
# do stuff that depends on lumping paths with the same endpoint together 

我的願望是一種方法來告訴by_endpoint使用Path.endpointkey功能,類似於key參數list.sort,並沒有把這個鍵定義進入Path課程本身(通過__eq____hash__),因爲同樣支持「通過起始點結塊」也同樣明智。

+0

這是否有什麼用'defaultdict'?聽起來就像你希望能夠基於對象的屬性而不是對象自己的默認相等和散列規則來散列對象?也就是說,你想能夠說'by_last_name [p]'並且根據對'p.last_name()'的調用結果進行無縫哈希和比較,是嗎?或者可能只是調用'p.last_name()'並將其存儲爲密鑰,而不是將'p'存儲爲密鑰? – ShadowRanger

+0

但是最後一個名字**是**的定義的一部分。一羣人可以通過姓氏散列,但這不是一個人。 – kabanus

+0

@ShadowRanger可能有不依賴於'defaultdict'的方法,但是,我試圖提供我正在處理的具體情況:製作一個'defaultdict',用於將類的實例「聚集在一起」他們的屬性不會將這個特性嵌入到類中。 – Dave

回答

0

事情是這樣的,也許:

from collections import defaultdict 

class defaultkeydict(defaultdict): 

    def __init__(self, default_factory, key=lambda x: x, *args, **kwargs): 
     defaultdict.__init__(self, default_factory, *args, **kwargs) 
     self.key_func = key 

    def __getitem__(self, key): 
     return defaultdict.__getitem__(self, self.get_key(key)) 

    def __setitem__(self, key, value): 
     defaultdict.__setitem__(self, self.get_key(key), value) 

    def get_key(self, key): 
     try: 
      return self.key_func(key) 
     except Exception: 
      return key 

注意,回落到傳入的密鑰,如果不能執行的關鍵功能的邏輯。這樣你仍然可以使用字符串或任何鍵訪問項目。

現在:

p = Path("Seattle", "Boston") 
d = defaultkeydict(list, key=lambda x: x.endpoint()) 
d[p].append(p) 
print(d)  # defaultdict(<type 'list'>, {'Boston': [<__main__.Path object at ...>]}) 
+0

這對我沒有幫助,因爲它涉及在課堂中放入'__key__'功能。我試圖避免這一點。 – Dave

+0

重寫將邏輯放在容器中而不是包含的對象。 – kindall