我有一个字符串
"{a:'b', c:'d',e:''}"
请注意,字典条目的键未加引号,因此在之前的问题中建议使用简单的
eval("{a:'b', c:'d',e:''}")
是不起作用的。将此字符串转换为字典的最便捷方式是什么?
{'a':'b', 'c':'d', 'e':''}
我有一个字符串
"{a:'b', c:'d',e:''}"
eval("{a:'b', c:'d',e:''}")
是不起作用的。{'a':'b', 'c':'d', 'e':''}
json
模块),你可以使用一个技巧来使用 eval
。source = """{e: '', a: 'b', c: 'd'}"""
class identdict(dict):
def __missing__(self, key):
return key
d = eval(source, identdict())
print(d)
打印
{'a': 'b', 'c': 'd', 'e': ''}
identdict
,它定义了魔法方法__missing__
。对于从字典中缺少的键进行查找时,会调用这个方法。在这种情况下,我们只返回键,所以字典将键映射到它们自身。然后使用一个identdict
实例作为globals
参数来eval
uate源代码。eval
将查找globals
映射中变量的值;由于它是一个identdict
,所访问的每个变量的值现在方便地是变量的名称。NameError
的,难道不应该在字典处理缺失值之前就引发了吗?它又是如何返回字符串的呢?我在 __missing__
方法中添加了 print(type(key))
,如果我像 id[1]
这样做,其中 id
是一个 identdict
,它会打印出 <class int>
,如果我做一些类似 id[x]
的事情,其中 x 没有被定义,我会得到一个 NameError
,__missing__
方法将永远不会被调用!很明显,我没有完全理解 eval
内置函数在做什么。 - juanpa.arrivillagaeval
。通常,eval
默认使用由调用globals()
和locals()
返回的这些映射;现在我们使用identdict
实例代替。 - Antti Haapala -- Слава Україні"{e: '', a: 'b', if: 'd'}"
无法成功执行。 - wims = "{a:'b', c:'d',e:''}"
d = dict([
(x.split(':')[0].strip(), x.split(':')[1].strip("' "))
for x in s.strip("{}").split(',')
])
手动解析容易出错且难以普遍适用,而基于eval
的方法在键是Python关键字时会失败。目前被接受的答案如果值包含空格、逗号或冒号,则会出现错误,而eval
答案无法处理像if
或for
这样的键。
相反,我们可以将输入作为一系列Python标记进行标记化,并将NAME
标记替换为STRING
标记,然后取消标记以构建有效的字典文字。从那里开始,我们只需调用ast.literal_eval
即可。
import ast
import io
import tokenize
def parse(x):
tokens = tokenize.generate_tokens(io.StringIO(x).readline)
modified_tokens = (
(tokenize.STRING, repr(token.string)) if token.type == tokenize.NAME else token[:2]
for token in tokens)
fixed_input = tokenize.untokenize(modified_tokens)
return ast.literal_eval(fixed_input)
parse("{a:'b', c:'d',e:''}") == {'a':'b', 'c':'d', 'e':''}
,并且关键字作为键或值中的特殊字符不会出现问题:>>> parse('{a: 2, if: 3}')
{'a': 2, 'if': 3}
>>> parse("{c: ' : , '}")
{'c': ' : , '}
警告 如果您的“字典”中间有映射到空字符串的键,则此方法将无法按预期工作。我不会删除此答案,因为我认为这种方法仍然可以挽救。
这可能比威尔的答案更通用,尽管它仍然取决于您正在解析的确切结构。如果您的键值对将由字母数字单词组成,则应该没问题。
In [3]: import re
In [4]: import itertools
In [5]: my_string = "{a:'b', c:'d',e:''}"
In [6]: temp = re.findall(r"\w", my_string)
In [7]: temp = itertools.zip_longest(temp[0::2], temp[1::2], fillvalue = "")
In [8]: dict(temp)
Out[8]: {'a': 'b', 'c': 'd', 'e': ''}
如果你想知道zip函数的运作原理,请参考以下问题:
我使用了itertools.zip_longest
,这样你就可以使用填充值,灵感来自于:
import re
str="{a:'b', c:'d',e:''}"
dict([i.replace("'","").split(":") for i in re.findall(r"(\w+\:'.*?')",str)])