何时使用ast.literal_eval

时间:2015-04-10 03:40:57

标签: python-3.x

我遇到了这段代码并且它有效,但我不完全确定何时使用ast 是否存在性能问题使用此代码而不是获取来自input()的字符串值并将其转换为int。

import ast

cyper_key = ast.literal_eval(input("Enter the key (a value between 0 and 25) : "))

# this get the user input as an int to the variable cyper_key

我阅读了我理解它的作用的文档。

  

这可以用于安全地评估包含Python的字符串   来自不受信任来源的值,无需解析值   自己。它无法评估任意复杂性   表达式,例如涉及运算符或索引。

我正在寻找上述大胆点的解释。

4 个答案:

答案 0 :(得分:7)

何时使用。

如果您期望用户列出(或类似的)列表,那么

ast.literal_eval(input())会很有用。例如,'[1,2]'将转换为[1,2]

如果用户应提供号码ast.literal_eval(input())可以替换为float(input()),或int(input())如果需要整数。


效果

请注意premature [micro-]optimization is the root of all evil.但是,因为你问:

要测试ast.literal_eval(input())float(input()的速度,您可以使用timeit

根据用户提供的输入,时间会发生变化

Ints和float是有效的输入,而其他任何东西都是无效的。给予50%的整数,40%的浮动和10%的随机输入,float(input()) x12 更快。

10%,10%,80%和float(input()) x6 更快。

import timeit as tt

lst_size = 10**5

# Set the percentages of input tried by user.
percentages = {'ints': .10,
               'floats': .10,
               'strings': .80}
assert 1 - sum(percentages.values()) < 0.00000001

ints_floats_strings = {k: int(v*lst_size) for k, v in percentages.items()}

setup = """
import ast

def f(x):
    try:
        float(x)
    except:
        pass

def g(x):
    try:
        ast.literal_eval(x)
    except:
        pass

l = [str(i) for i in range({ints})]
l += [str(float(i)) for i in range({floats})]
l += [']9' for _ in range({strings}//2)] + ['a' for _ in range({strings}//2)]
""".format(**ints_floats_strings)

stmt1 = """
for i in l:
    f(i)
"""

stmt2 = """
for i in l:
    g(i)
"""


reps = 10**1
t1 = tt.timeit(stmt1, setup, number=reps)
t2 = tt.timeit(stmt2, setup, number=reps)

print(t1)
print(t2)

print(t2/t1)

答案 1 :(得分:1)

如果它将用作int,那么只需使用:

cypher_key = int(input("Enter the key (a value between 0 and 25) : "))

如果您希望用户输入10e7或其他内容,请仅使用该功能。如果你想处理不同的基础,你可以使用int(input(...), 0)自动神圣基础。如果它确实是0到25之间的整数值,则没有理由使用ast

答案 2 :(得分:0)

shell中运行它,当我给出正确的输入时,我没有区别:

>>> cyper_key = ast.literal_eval(input("Enter the key (a value between 0 and 25) : "))
Enter the key (a value between 0 and 25) : 5
>>> cyper_key
5

但是,当您提供字符串或无法转换的内容时,错误可能会造成混淆和/或误导:

>>>  cyper_key = ast.literal_eval(input("Enter the key (a value between 0 and 25) : "))
Enter the key (a value between 0 and 25) :  foo
Traceback (most recent call last):
  File "python", line 3, in <module>
ValueError: malformed node or string: <_ast.Name object at 0x136c968>

但是,如果您不想将floatint投射到您的输入中,这可能很有用,这可能导致ValueErrorsintfloatast的浮点数。

因此,我发现在使用{{1}}解析您的输入时没有使用必要,但它可以作为替代。

答案 3 :(得分:0)

ast -> Abstract Syntax Trees 
如果输入不是有效的Python数据类型,则

ast.literal_eval会引发异常,因此如果代码不是,则不会执行代码。 这个链接AST对您有用了解。