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?
1 Answer 1
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
evalis usually associated with risky operations, what you are missing though is likely using string interpolation you want the value ofanot justavariable. Try '{} () {}'.format(a, b).replace....`