我发现代码如下:
nav_str = "'\\'!@34QWer\\''"
native_structure = eval(nav_str, {'__builtins__':{'set' : set}}, {})
>>> native_structure
>>> '!@34QWer'
我只是想知道eval(nav_str, {'__builtins__':{'set' : set}}, {})
如何将"'\\'!@34QWer\\''"
转移到'!@34QWer'
更新:
我试着了解@user2357112
和@Blender
几分钟,但我仍然无法实现这一过程
作为回答者,我认为eval("'\\'!@34QWer\\''")
应该返回'\\'!@34QWer\\''
,但'\\'!@34QWer\\''
无效。
在eval()中"'\\'!@34QWer\\''"
的演变过程是什么?
答案 0 :(得分:1)
让我们看看nav_str
的内容,没有字符串文字的转义:
>>> print nav_str
'\'!@34QWer\''
这些是nav_str
包含的文字字符。单引号,反斜杠,单引号,感叹号等。这些字符构成有效的Python字符串文字。 eval
计算字符串文字,返回一个字符串。
答案 1 :(得分:1)
首先,我们来看看这部分:
eval(nav_str, {'__builtins__':{'set' : set}}, {})
通常,eval
会评估您在正常环境中给出的表达式,因此这些表达式相同:
>>> def foo(): print 'Hi'
>>> foo()
Hi
>>> eval('foo()')
Hi
但有时候你不想那样。您可能不希望在正常环境中从网络中取出任意字符串并eval
,除非您想让人们(例如__import__('os').system('rm -rf /')
)。因此,您可以自定义评估表达式的环境。具体细节在上面的文档中描述,但这是一个简单的示例:
>>> def foo(): print 'Hi!'
>>> def bar(): print 'Bye!'
>>> eval('foo()')
Hi!
>>> eval('foo()', {'__builtins__': {}}, {})
NameError: name 'foo' is not defined
>>> eval('foo()', {'__builtins__': {'foo': bar}}, {})
Bye!
那么,为什么你会想要一个除了set
之外没有名字的环境?
最有可能的原因是你想要像ast.literal_eval
这样的东西,但这也提供了一些处理空集的方法。 literal_eval
仅评估Python文字。但空集没有字面意思;你必须写set()
。并且ast.literal_eval
无法处理set()
。但是,在您的示例中对eval
的错综复杂的调用可以。
当然这并不完美。使用eval
允许所有类型的表达式不使用名称 - 数学,列表推导,生成器表达式,......
现在,让我们看看你正在评估的字符串:
nav_str = "'\\'!@34QWer\\''"
嗯,那里没有set
的电话。或者完全引用任何名称。所以额外的复杂性只是一个红色的鲱鱼。只用eval(nav_str)
就可以得到完全相同的东西。
那么,该字符串的处理是什么?
好吧,比较一下:
>>> print '\'!@34QWer\''
'!@34QWer'
>>> print eval(r"'\'!@34QWer\''")
'!@34QWer'
>>> print eval("'\\'!@34QWer\\''")
'!@34QWer'
您需要的唯一理由
它看起来如此复杂的唯一原因是:(a)编写表达式的人坚持使用单引号,即使字符串本身内部有单引号,需要反斜杠转义,以及(b)编写存储表达式的代码的人在变量中坚持不使用原始字符串,需要将这些反斜杠加倍。
您可以编写一个没有反斜杠的等效表达式:
>>> nav_str = '''"'!@34QWer'"'''
(它不是相同的字符串文字表达式,但它是一个字符串文字表达式,其计算结果相同。)