如何用eval与f-strings实现等价is判断得到True结果
问题原因
两种错误写法的核心问题都是把对象本身的字符串表示直接拼接到了待执行的代码串里:
- 直接用
{x}插值时,会触发对象的__str__方法,type.__dict__是mappingproxy对象,它的字符串形式包含<slot wrapper '__repr__' of 'type' objects>这类不属于合法Python语法的片段,拼出来的代码本身就有语法错误,自然抛出SyntaxError。 - 用
{x!r}调用__repr__插值时,虽然输出格式更贴合Python代码规范,但首先mappingproxy这个名称默认不在eval的执行命名空间中,就算你手动导入对应类做别名,通过repr结果重新构造的新对象和原x也不是同一个内存对象,is判断会返回False,完全达不到预期效果。
正确写法
eval执行的是字符串形式的Python代码,不需要把实际对象硬转成字符串拼进去,只需要在代码串里写变量名,把真实对象通过eval的命名空间参数传入即可,从根源上避免语法错误,也能保证身份判断的准确性:
x = type.__dict__ operator = 'is' # 表达式中用临时变量名占位,将真实x作为命名空间传入 result = eval(f'a {operator} b', {}, {'a': x, 'b': x}) print(result) # 输出:True
如果不需要隔离执行环境,也可以直接在表达式中引用当前上下文的变量名,不需要手动传命名空间:
x = type.__dict__ operator = 'is' result = eval(f'x {operator} x') print(result) # 输出:True
注意:
eval存在安全风险,如果操作符、操作数来自不可信的外部输入,不建议使用该方式实现逻辑。
内容的提问来源于stack exchange,提问作者apostofes
相关产品推荐
相关产品推荐

