2013-05-10 50 views
-1
class FrozenDict(dict): 
    def __init__(self,default=None): 
     if default: self.update(default) 
    def __hash__(self): 
     return id(self) 


dictionary={FrozenDict({"dsa":"saas"}):"Hi"} 

eval(str(dictionary)) 


TypeError: unhashable type: 'dict' 

我想將一個字符串轉換爲原始格式,所以我沒有收到錯誤。字典的 '原始' 的形式是{FrozenDict({"dsa":"saas"}):"Hi"}將Python字符串轉換爲原始格式

事情是這樣的:

eval(rawform(dictionary)) 

將是真棒..

編輯:

OrderedDict似乎工作,沒有人知道爲什麼嗎?

編輯:

這就是我試圖使用pickle.loads

S'{\'Source\': {\'CollideObjects\': [], \'Depth\': 0, \'Events\': OrderedDict([(({\'function\': \'bi_create\', \'class\': \'\', \'name\': \'Create\'}, 0), {{\'data\': {\'raw\': \'Set saddasdsadsa to: (,)\', \'data\': {u\'function\': u\'asddsaadsasddsasdasdasddsasdasda(x=None,y=None)\', u\'src\': u\'GUI\\\\movetoxy.xml\', \'code\': u\'\\nreal=[0,0]\\ncurrent=self.sdsdadsaadssd()\\nif x!=None:\\n\\treal[0]=float(x)\\nelse:\\n\\treal[0]=current[1]\\nif y!=None:\\n\\treal[1]=float(y)\\nelse:\\n\\treal[1]=current[1]\\nself.SetPos(*real)\\n\', \'return\': u"\'Set Position to: (\'+str(x)+\',\'+str(y)+\')\'", u\'title\': u\'Set Position\', u\'image\': u\'modules\\\\Core\\\\images\\\\pos.png\', \'dddddddddd\': u\'self.SetPosition(,)\', \'html\': u\'C:\\\\sadsdadsad\\\\dsasasddsa\\\\modules\\\\Core\\\\GUI\\\\movetoxy.xml\', \'apply\': {\'name\': \'Self\', \'value\': \'\'}, u\'holder\': u\'False\', u\'class\': u\'object\'}, \'dialog\': u\'Set Position\', \'name_var\': {u\'y\': {\'class\': u\'wxTextCtrl\', \'value\': u\'\'}, u\'x\': {\'class\': u\'wxTextCtrl\', \'value\': u\'\'}}}}: {}})]), \'Sprite\': \'\'}, \'Window\': \'\', \'Type\': \'Object\', \'Name\': u\'Object1\', \'Id\': 1}' 
+0

不要只爲'__hash__'返回'id(self)';這使得您的密鑰不可能再次找到。 – 2013-05-10 17:19:29

+0

嗯,我從互聯網上了解到,你對我應該改變什麼有什麼建議嗎? – 2013-05-10 17:20:40

+0

請參閱http://docs.python.org/2/reference/datamodel.html#object.__hash__關於'__hash__'方法應該做什麼。 – 2013-05-10 17:22:52

回答

1

要創建 「rawform」,你需要重寫__repr__

class FrozenDict(dict): 
    def __init__(self,default=None): 
     if default: self.update(default) 
    def __hash__(self): 
     return id(self) 
    def __repr__(self): 
     return "FrozenDict(%s)" % dict.__repr__(self) 


print FrozenDict({"dsa":"saas"}) 

dictionary={FrozenDict({"dsa":"saas"}):"Hi"} 

print eval(str(dictionary)) 

結果我得到:

FrozenDict({'dsa': 'saas'}) 
{FrozenDict({'dsa': 'saas'}): 'Hi'} 
3

加載爲了這個目的,沒有任何理由,你不能pickle它呢?

import cPickle as pickle 
# This can't be `eval`d, but... 
string = pickle.dumps(dictionary) 
# ... you can use it to get back the original object 
obj = pickle.loads(string) 

當然,它並沒有利用eval,但如果能夠避免使用eval,它應該是。

+0

嗯很酷。生病試試 – 2013-05-10 17:25:37

+0

Im實際上將字典存儲在sqlite3表中,當我從表中加載字典時,我得到'TypeError:必須是字符串,而不是unicode',你知道解決這個問題的最佳方法嗎? – 2013-05-10 17:30:45

+0

也許你可以包括一個你遇到問題的數據的例子,然後我們可以更容易地診斷:-) – 2013-05-10 17:32:19

1

有幾個問題與你在做什麼。

首先,你eval不工作的原因是因爲你還沒有覆蓋的__repr__方法在FrozenDict類,所以eval是生產普通的字典,而不是一個新的FrozenDict,並得到一個錯誤試圖使用時它作爲字典的關鍵。這是比較容易解決:

def __repr__(self): 
    return "FrozenDict({})".format(super(FrozenDict, self).__repr__()) 

這將讓你使用你的對象作爲Python代碼的strrepr重新創建它。

但是,還有一些其他問題沒有解決。舉例來說,目前你可以有不同的哈希,即使他們的比較結果相等的詞典:

a = FrozenDict({"foo":"bar"}) 
b = FrozenDict({"foo":"bar"}) 

a == b    # True! 
hash(a) == hash(b) # False! 

這使得它不可能匹配哈希表的冷凍字典如果你使用完全相同的對象沒有做當你插入它。

更好的方法可能會根據字典中的鍵和值來計算散列。像這樣的東西會做的更好:

def __hash__(self): 
    return hash(tuple(sorted(self.items())) 

不過,現在你會碰到另外一個問題:你的字典是可變的,如果你把它添加或刪除其值散列可以改變。這是非常糟糕:

a = FrozenDict() 
d = {a: "a"} 

a["foo"] = "bar" 

d[a]   # raises a KeyError! 
d[FrozenDict()] # perhaps surprisingly, so does this! 

要解決這個問題,你可能需要重寫__setitem____delitem__update引發異常他們調用時。我想,如果你知道在將它們添加到字典後你不會修改這些值,那麼你可以跳過這個,但是如果你希望你的類更普遍有用的話,這是必要的。可能還有一些我已經忘記的其他突變方法。

相關問題