2013-04-13 38 views
2

我想作爲一個類內的字典參數的列表。 由於數據的性質,一些參數是從其他參數派生的,但經常使用,我寧願將它們的派生保留在參數字典中。 我已經設法將自我參考字典放在一起,它可以直接命名字典,但因爲它是類的一部分,並且可能在許多不同的文件中實現,所以我很難使其獲得該字典能夠自己命名。Python的自我參考字典與類

class foo: 
    class ParamDict(dict): 
     def __getitem__(self, key): 
      val = dict.__getitem__(self, key) 
      return callable(val) and val() or val 

    params = ParamDict({ 
     'a': 5, 
     'b': lambda: 2**self['a'] 
     }) 

if __name__ == '__main__': 
    X = foo() 
    Y = foo() 
    Y.params['a'] = 3 

    print X.params['a'], X.params['b'] 
    print Y.params['a'], Y.params['b'] 

因爲我不知道在哪裏lambda函數將被調用,從我不知道如何給它的參考字典,它似乎並沒有拿起從「自我」 getitem定義,不幸的是。 有什麼建議嗎?

+0

你爲什麼不能傳遞'self'到''中__getitem__' val'? '返回可調用(val)和val(自己)或val'?很明顯,lambda必須得到自我:''b':lambda self:2 ** self ['a']'。 – gatto

+0

任何不使用函數的理由是什麼? –

+0

你不能在沒有實例的情況下引用'self'。定義一個類時,不存在* yet *的實例。如果'b'參數中的'self'是爲了引用'params'實例,那麼您需要*將它傳遞給*函數。 –

回答

3

self不只是神奇地出現; Python函數在通過實例訪問時(通過invoking the function as a descriptor)被封裝在方法中,然後self作爲第一個參數傳遞給函數。

爲了您的lambda表達式,你需要在通過self明確

class ParamDict(dict): 
    def __getitem__(self, key): 
     val = dict.__getitem__(self, key) 
     return callable(val) and val(self) or val 

params = ParamDict({ 
    'a': 5, 
    'b': lambda self: 2**self['a'] 
    }) 
+0

是的,謝謝 - 這有效,我知道我在那裏失去了一些東西。雖然這樣做雖然它似乎修改底層類字典而不是類字典的實例(在上面的代碼中改變Y.params也改變了X.params),但我認爲這可能不是我的頭圍繞下面發生的事情。 – benjsec

+0

@benjsec:這是因爲'params'是* class屬性*。如果你需要每個副本的'params',然後在類的'__init__'中創建它。 –

+0

@MartijnPieters,如果可調用(val)else val',你可以用當代'val(self)'代替'callable(val)和val(self)或val'嗎? –