原始字符串到 python 字典(?)

Wes*_*mer 1 python string dictionary

我首先创建一个字典作为原始字符串,然后使用 b = eval(raw string) 定义 b。当我将原始字符串剪切并粘贴到 python 控制台时,效果很好,但是当我运行程序时,出现错误“TypeError:字符串索引必须是整数”

最小代码示例:

def drawBoardData2():
    cells = ''
    cells+=("r\'{")
    for r in range(0,2):
        c = 2
        cc = "light"
        piece = "b"
        player = "A"
        if r != 1:
            comma = ","
        else:
            comma = ""
        cells += ("\"{r}.{c}\":[1,1,\"{color}\",\"{pi}\",\"{pl}\",\"none\"]{cm} ".format(r=r, c=c, color=cc, pi=piece, pl=player, cm=comma))
    cells += ("}\'")
    #print("}\'")
    print(cells)
    b = eval(cells)
    print(b)
    print(type(b)) # result: <class 'str'> instead of <class 'dict'>
    b["1.2"] # result: "TypeError: string indices must be integers"

drawBoardData2()
Run Code Online (Sandbox Code Playgroud)

代码给了我cells=r'{"0.2":[1,1,"light","b","A","none"], "1.2":[1,1,"light","b","A","none"] }' print(type(b))给了我<class 'str'>而不是<class 'dict'>. 如果我将其剪切并粘贴到 PyCharm 的控制台中,并使用该eval()命令,它会给我一本字典。有谁知道为什么它在控制台中有效,但在我运行程序时却不起作用?

我怎样才能解决这个问题?我ast也尝试过,但得到了相同的结果:

import ast
b = ast.literal_eval(cells)
print(type(b)) # <class 'str'>
# still gives me a string instead of a dictionary
# unless I copy & paste the raw string and use it in the console, then it works fine
Run Code Online (Sandbox Code Playgroud)

也许我需要使用不同的引号,或者转义引号?我认为使用原始字符串可以解决这个问题。

Sha*_*ger 5

正如所写,您只需更改即可使其工作:

\n
b = eval(cells)\n
Run Code Online (Sandbox Code Playgroud)\n

到:

\n
b = eval(eval(cells))\n
Run Code Online (Sandbox Code Playgroud)\n

或者稍微更安全/更好:

\n
b = ast.literal_eval(ast.literal_eval(cells))\n
Run Code Online (Sandbox Code Playgroud)\n

这是有效的,因为您没有构建一个“代表 a 的字符串dict”,而是构建了一个“代表代表 a 的原始字符串文字的字符串dict”;它周围有两层“字符串”,需要对其进行eval两次 -ed 才能获得其dict自身。当您只evaled 一次时,您得到了由您 -ed 的原始字符串文字表示的字符串eval,但您没有将其转换为dict.

\n

也就是说,您似乎对原始字符串的价值有点困惑;构建包含原始字符串定义的字符串对您来说没有多大作用,因为您插入的值首先不会有反斜杠转义(当它们有反斜杠时,它们会' re 可能并不意味着逃避)。因此,更好的解决方案是避免原始字符串换行,因此您构建一个表示 a 的字符串dict,而不是构建一个表示 a 的字符串dict。改变只是改变:

\n
cells = \'\'\ncells+=("r\\\'{")\n...\ncells += ("}\\\'")\n
Run Code Online (Sandbox Code Playgroud)\n

到:

\n
cells = "{"\n...\ncells += "}"\n
Run Code Online (Sandbox Code Playgroud)\n

(去掉一堆你在讨价还价中不需要的东西)

\n

这会让您回到只需要一层eval/ ast.literal_eval

\n

也就是说,使用eval/似乎相当愚蠢ast.literal_eval。直接构建实际dict似乎是明智的解决方案:

\n
import json\n\ndef drawBoardData2():\n    cells = {}\n    for r in range(0,2):\n        cells[f\'{r}.2\'] = [1, 1, "light", "b", "A", "none"]\n    print(cells)\n    print(json.dumps(cells))\n\ndrawBoardData2()\n
Run Code Online (Sandbox Code Playgroud)\n

wherejson.dumps可让您将其转换为始终使用双引号的字符串形式(假设这是设计要求)。

\n

在线尝试一下!

\n