I want to use eval
to do operations to see if a
and b
equals c
with some operator.
My code:
def Expression(a, b, c):
operators = ["+", "-", "*", "/"]
return len([i for i in operators if eval("a () b".replace("()", i)) == c]) >= 1
Expression(1, 2, 3)
For some reason, this results in a NameError. Error log:
return len([i for i in operators if eval("a () b".replace("()", i)) == c]) >= 1
File "<string>", line 1, in <module>
NameError: name 'a' is not defined
Since the function has a
as a parameter I don't believe a
should be undefined. What is the problem here?
The problem is in that case eval
try to find a
and b
in global scope, not function scop(it means that a
and b
is just valid in the function block). so you can pass the function current scope using locals()
to eval
like this:
def Expression(a, b, c):
operators = ["+", "-", "*", "/"]
scope = locals()
return len([i for i in operators if eval("a () b".replace("()", i), scope) == c]) >= 1
Then your code will work.
for better understanding try to define a
and b
in the global scope, then you can see it works, like this:
a=1
b=2
def Expression(c):
operators = ["+", "-", "*", "/"]
return len([i for i in operators if eval("a () b".replace("()", i)) == c]) >= 1
Expression(3)
Also, you can pass a custom scope to eval by creating a dictionary and pass it to eval
:
scope = {'a':a, 'b':b}
So, it was your code problem. but for the better attitude you can use what @Rakesh said before, Using formatted strings, it gets the current a
and b
and pass it to eval as what they have inside, like this:
eval(f"{a}{i}{b}") # <Python3.6
eval("{}{}{}".format(a,i,b))
Also you can use any() instead of len() >= 1