将Python字符串转换为Raw Form

时间:2013-05-10 17:15:58

标签: python

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

3 个答案:

答案 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__())

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