python中eval()函数实际应用的一个疑问?

题目描述

获取一个随机验证码并通过eval()函数校对是否与用户输入值一致

题目来源及自己的思路

我的思路是直接eval函数进行计算字符串表达式,但不行,后来发现新建一个变量可以完成完整代码,如我注释掉的两行代码,但我不明白为什么我这种直接调用的不行?

相关代码

粘贴代码文本(请勿用截图)
import random

a = str(random.randint(0, 10))                    
b = str(random.randint(0, 10))                    
x = input(f"请输入计算验证信息的结果({a}+{b}):")              
# y = f"{a} + {b}"                                
# r = eval(y)                                     
r = str(eval('a + b'))                            
if x == str(r):                                   
    print("您已经通过验证!")                             
else:                                             
    print("您的验证信息输入有误!")                          
                                                  

你期待的结果是什么?实际看到的错误信息又是什么?

我希望看到我验证成功
实际看到的截图如下
image.png

阅读 2.3k
2 个回答

eval('a + b') eval需要在上下文中查找,ab的值的。很显然,并没有在上下文中设置a, b的值。

eval(expression[, globals[, locals]])
- expression -- 表达式。
- globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
- locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。

所以,你这样写才可以

>>> a = 3
>>> b = 4
>>> eval('a+b', {'a': a, 'b': b})
7

关于globalslocals你可以在这里看下。

https://docs.python.org/3/lib...
https://docs.python.org/3/lib...
https://docs.python.org/3/lib...

eval('a+b', {'a': a, 'b': b}) 其实就是在 globals() 全局命名空间中添加了如下:

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': 3, 'b': 4}

其实问题是因为你的 ab 是字符串,导致你的 eval('a + b') 其实是对于两个字符串先进行了字符串的拼接( eval('"a" + "b"') = eval('ab') = ab ),才再次执行了 eval 的计算。所以你始终得到的结果是a和b字符串的拼接,而不是数字的相加。

也就是说:

import random

a = str(random.randint(0, 10))    # a是一个字符串
b = str(random.randint(0, 10))    # b是一个字符串
x = input(f"请输入计算验证信息的结果({a}+{b}):")
r = str(eval('a + b'))    # 其实等价于 eval('str(a) + str(b)') => eval('"a" + "b"') => eval('ab')

# print(r):假设a是'5',b是'6',那么r是'56' <=> eval('"5" + "6"')

if x == str(r):
    print("您已经通过验证!")
else:
    print("您的验证信息输入有误!")

所以如果你把 ab 前面的str这个给去掉,a和b就是整型变量,然后你的写法就是对的了。

改进如下:

# 写法一:
import random

a = random.randint(0, 10)    # 去掉这里的str,不需要转换为string类型
b = random.randint(0, 10)    # 去掉这里的str,不需要转换为string类型
x = input(f"请输入计算验证信息的结果({a}+{b}):")
r = str(eval('a + b'))
if x == str(r):
    print("您已经通过验证!")
else:
    print("您的验证信息输入有误!")

# 写法二:
import random

a = str(random.randint(0, 10))
b = str(random.randint(0, 10))
x = input(f"请输入计算验证信息的结果({a}+{b}):")
r = str(eval(f"{a} + {b}"))    # 将这里的表达式改成f"{a} + {b}", 这样eval里面就是纯粹的 a + b, 而不是"a" + "b".
if x == str(r):
    print("您已经通过验证!")
else:
    print("您的验证信息输入有误!")
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题