2013-05-10 72 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引发异常他们调用时。我想,如果你知道在将它们添加到字典后你不会修改这些值,那么你可以跳过这个,但是如果你希望你的类更普遍有用的话,这是必要的。可能还有一些我已经忘记的其他突变方法。

相关问题