-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"}

像这样的东西:

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}'
4

3 回答 3

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可以避免使用,它应该是。

于 2013-05-10T17:24:11.527 回答
1

你正在做的事情有几个问题。

首先,您eval不起作用的原因是因为您没有覆盖类中的__repr__方法FrozenDict,因此eval生成常规字典而不是新字典FrozenDict,并且在尝试将其用作字典键时出现错误。这相对容易修复:

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

这将允许您使用对象的strorrepr作为 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在调用异常时引发异常。我想如果您知道在将值添加到字典后不会修改这些值,您可以跳过此步骤,但如果您希望您的课程更普遍有用,这是必要的。可能还有一些我也忘记了的其他突变方法。

于 2013-05-10T17:53:52.603 回答
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'}
于 2013-05-10T17:40:15.587 回答