What does Python's eval() do?
在我读的关于python的书中,它一直使用代码
我阅读了文档,并且理解了它,但是我仍然看不到它如何改变
它是做什么的?有人能解释吗?
eval函数允许一个python程序在其内部运行python代码。
eval示例(交互式shell):
1 2 3 4 5 | >>> x = 1 >>> eval('x + 1') 2 >>> eval('x') 1 |
这里有很多很好的答案,但没有一个描述在其
这些方法可用于限制通过
1 2 3 4 | >>> globals() {'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__package__': None, '__name__': '__main__'} |
在
1 2 3 | >>>from os import cpu_count() >>>eval('[1, cpu_count()]') [1, 8] |
同样,所有的
1 2 | >>>eval('abs(-1)') 1 |
好啊。在这里,我们看到一个我们想要公开的方法和一个我们不想要公开的方法的例子(很多方法中的一个可能更复杂)。所以让我们封锁一切。
1 2 | >>>eval('[1, cpu_count()]', {'__builtins__':None}, {}) TypeError: 'NoneType' object is not subscriptable |
我们已经有效地阻止了所有的
1 2 3 4 5 6 | >>>from os import cpu_count >>>exposed_methods = {'cpu_count': cpu_count} >>>eval('cpu_count()', {'__builtins__':None}, exposed_methods) 8 >>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods) TypeError: 'NoneType' object is not subscriptable |
现在我们有了cpu-count方法,同时仍然可以阻止我们不想要的一切。在我看来,这是超级强大的,从其他答案的范围来看显然不是一个共同的实现。这样的东西有很多用途,只要处理得当,我个人认为
N.B.
这些
1 2 3 | >>>from os import cpu_count >>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()}) [1, 8] |
在python 2.x中,
在这种情况下,使用
您可能会感到困惑的一个原因是,您引用的代码涉及一个间接级别。首先执行内部函数调用(input),以便用户看到"blah"提示。假设它们的响应是"1+1"(为了清晰起见,添加了引号,在运行程序时不要键入引号),输入函数将返回该字符串,然后将其传递给外部函数(eval),后者将解释该字符串并返回结果(2)。
在这里阅读更多关于eval的信息。
顾名思义,
因此,
简而言之:
1 2 3 4 | running_params = {"Greeting":"Hello"} fout = open("params.dat",'w') fout.write(repr(running_params)) fout.close() |
将其作为变量读取并编辑:
1 2 3 4 5 | fin = open("params.dat",'r') diction=eval(fin.read()) diction["Greeting"]+="world" fin.close() print diction |
输出:
1 | {'Greeting': 'Hello world'} |
也许是一个读一行并解释它的误导例子。
尝试
我回答这个问题迟到了,但似乎没有人对这个问题给出明确的答案。
如果用户输入一个数值,
1 2 3 4 5 6 | >>> input('Enter a number: ') Enter a number: 3 >>> '3' >>> input('Enter a number: ') Enter a number: 1+1 '1+1' |
因此,
1 2 3 4 5 6 7 | >>> eval(input('Enter a number: ')) Enter a number: 1+1 2 >>> >>> eval(input('Enter a number: ')) Enter a number: 3.14 3.14 |
当然,这是一种不好的做法。在这种情况下,应使用
1 2 3 | >>> float(input('Enter a number: ')) Enter a number: 3.14 3.14 |
如果要将评估字符串限制为简单文本,另一种选择是使用
1 2 3 4 5 6 7 8 | import ast # print(ast.literal_eval('')) # SyntaxError: unexpected EOF while parsing # print(ast.literal_eval('a')) # ValueError: malformed node or string # print(ast.literal_eval('import os')) # SyntaxError: invalid syntax # print(ast.literal_eval('1+1')) # 2: but only works due to a quirk in parser # print(ast.literal_eval('1*1')) # ValueError: malformed node or string print(ast.literal_eval("{'a':1}")) # {'a':1} |
来自文档:
Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.
This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.
至于为什么它如此有限,从邮件列表中可以看出:
Allowing operator expressions with literals is possible, but much more complex than the current implementation. A simple implementation is not safe: you can induce basically unbounded CPU and memory usage with no effort (try"9**9**9" or"[None] * 9**9").
As for the usefulness, this function is useful to"read back" literal values and containers as stringified by repr(). This can for example be used for serialization in a format that is similar to but more powerful than JSON.