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"}
这样的事情:
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 :(得分: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
,那么它应该是。
答案 1 :(得分: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'}
答案 2 :(得分:1)
你正在做的事情有几个问题。
首先,您的eval
无效的原因是您没有覆盖__repr__
课程中的FrozenDict
方法,因此eval
正在制作常规字典而不是新的FrozenDict
,并在尝试将其用作字典键时出错。这相对容易修复:
def __repr__(self):
return "FrozenDict({})".format(super(FrozenDict, self).__repr__())
这将允许您使用对象的str
或repr
作为Python代码来重新创建它。
但是,还有其他一些问题无法解决。例如,目前您可以使用不同的字典,即使它们相等也是如此:
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
以在调用时引发异常。我想如果你知道在将它们添加到字典后你不会修改它们,你可以跳过这个,但是如果你希望你的类更普遍有用,那么这是必要的。可能还有一些我已经忘记的突变方法。