When to use ast.literal_eval
If it's going to be used as an int
, then just use:
cypher_key = int(input("Enter the key (a value between 0 and 25) : "))
Only use that if you expect the user to be entering 10e7
or something. If you want to handle different bases, you can use int(input(...), 0)
to automatically divine the base. If it really is an integer value between 0 and 25, there's no reason to use ast
.
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)