Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
520 views
in Technique[技术] by (71.8m points)

python 3.x - When to use ast.literal_eval

I came across this code and it works, but I am not entirely sure about when to use ast and whether there are performance issues when this is used instead of getting the string value from input() and converting it to 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

I read the docs I understand what it does.

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.

I am looking for an explanation on above bold points.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When to use it.

ast.literal_eval(input()) would be useful if you expected a list (or something similar) by the user. For example '[1,2]' would be converted to [1,2].

If the user is supposed to provide a number ast.literal_eval(input()) can be replaced with float(input()), or int(input()) if an integer is expected.


Performance

Note that premature [micro-]optimization is the root of all evil. But since you asked:

To test the speed of ast.literal_eval(input()) and float(input() you can use timeit.

Timing will vary based on the input given by the user.

Ints and floats are valid input, while anything else would be invalid. Giving 50% ints, 40% floats and 10% random as input, float(input()) is x12 faster.

With 10%, 10%, 80% and float(input()) is x6 faster.

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...