2012-06-12 69 views
2

我有傾倒多個defaultdict用一個簡單的打印命令,就像這樣:解析defaultdict串

defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 

有一些標準的解析器,我可以用它來獲取它們?我知道我應該使用pickle,但生成這些defaultdict的代碼非常慢,我想避免重新運行它。

回答

2

完全難看,但工作原理:

s = """ 
defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 
""" 

import re, ast 

s = re.sub('^[^{]+', '', s) 
s = re.sub('[^}]+$', '', s) 

print ast.literal_eval(s) 

請注意,這將創建一個普通的dict,不是defaultdict。

+0

推測,你也可以使用內置的JSON解析器。 –

+0

使用'ast'的+1。 –

5

如果defaultdict的類型總是<type 'list'>,您可以使用以下命令:

from collections import defaultdict 

s = """ 
defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 
""" 
data = eval(s.replace("<type 'list'>", 'list')) 

的人會告訴你,eval()是不安全的,邪惡的,但如果有人試圖注入惡意代碼到數據你甩了,他們可能就像編輯你的源代碼一樣簡單。如果您從中獲取該數據的文本文件比源代碼更易於訪問,那麼您可能不想使用此方法。

如果有多個類型的defaultdicts,但他們都是內置類型(或易repr和類型名之間進行轉換),那麼你仍然可以使用此方法有多種替代品,例如:

for rep, typ in ((repr(list), 'list'), (repr(dict), 'dict')): 
    s = s.replace(rep, typ) 
data = eval(s) 
+0

+1使用'eval';) – georg

0

你可以讓自己的子類:

from collections import defaultdict 

class mydefdict(defaultdict): 
    def __repr__(self): 
     return "mydefdict(%s, %s)" % (repr(self.default_factory()) + ".__class__", repr(dict(self))) 

,然後用eval使用它像其他類型:

>>> d = mydefdict(list) 
>>> d['foo'] = [1,2,3] 
>>> d['bar'] 
[] 
>>> print d 
mydefdict([].__class__, {'foo': [1, 2, 3], 'bar': []}) 
>>> reprstring = repr(d) 
>>> d2 = eval(reprstring) 
>>> d2 
mydefdict([].__class__, {'foo': [1, 2, 3], 'bar': []}) 

請注意,使用這種方式,即使某些對同一對象的引用,也會爲結構中的每個對象引用創建單獨的副本。