You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python计算器开发:eval函数的实现难题

解决计算器中eval函数的集成问题

核心问题分析

你的代码中result = eval(self.equation)出现问题,主要原因有两点:

  1. 异常处理不完整:仅捕获了ZeroDivisionError,但eval可能抛出SyntaxError(表达式格式错误)、NameError(存在未定义变量)等其他异常,未处理的异常会导致程序崩溃。
  2. 输入验证环节缺失:仅验证了右侧输入displayText,但未检查self._left是否为有效数字、self._op是否为合法运算符,这会导致生成的self.equation是无效表达式,触发eval执行失败。

解决方案

方案一:保留eval但完善验证与异常处理

通过增强输入校验、捕获所有可能的异常,确保eval执行稳定:

def _eq(self):
    displayText = self.display.text()

    if not isValidNumber(displayText):
        print('右侧无有效数字')
        return
    
    # 验证运算符是否为合法算术运算符
    valid_ops = {'+', '-', '*', '/'}
    if self._op not in valid_ops:
        print('无效运算符')
        return
    
    # 验证左侧数字有效性
    if not isinstance(self._left, (int, float)):
        print('左侧无有效数字')
        return

    self._right = float(displayText)
    self.equation = f'{self._left} {self._op} {self._right}'
    result = 0.0

    try:
        result = eval(self.equation)
    except ZeroDivisionError:
        print('除数不能为零')
        return
    except SyntaxError:
        print('表达式语法错误')
        return
    except NameError:
        print('表达式包含未定义变量')
        return
    except Exception as e:
        print(f'计算出错: {str(e)}')
        return

    self.display.clear()
    self.info.setText(f'{self.equation} = {result}')
    self._left = result
    self._right = None

方案二:用安全方式替代eval(推荐)

eval存在安全风险(若输入恶意代码可能执行),建议使用operator模块实现算术运算,彻底规避风险:

import operator

# 定义运算符与对应函数的映射
OPERATOR_MAP = {
    '+': operator.add,
    '-': operator.sub,
    '*': operator.mul,
    '/': operator.truediv
}

def _eq(self):
    displayText = self.display.text()

    if not isValidNumber(displayText):
        print('右侧无有效数字')
        return
    
    # 验证运算符合法性
    if self._op not in OPERATOR_MAP:
        print('无效运算符')
        return
    
    # 验证左侧数字有效性
    if not isinstance(self._left, (int, float)):
        print('左侧无有效数字')
        return

    self._right = float(displayText)
    result = 0.0

    try:
        # 通过映射调用对应运算函数,替代eval
        result = OPERATOR_MAP[self._op](self._left, self._right)
    except ZeroDivisionError:
        print('除数不能为零')
        return
    except Exception as e:
        print(f'计算出错: {str(e)}')
        return

    self.display.clear()
    self.info.setText(f'{self._left} {self._op} {self._right} = {result}')
    self._left = result
    self._right = None

关键改进点说明

  • 新增self._op和self._left的有效性校验,从源头避免生成无效计算表达式。
  • 扩展异常捕获范围,确保所有可能的错误都能被处理,避免程序崩溃。
  • 方案二彻底移除eval,消除安全隐患,同时保证计算逻辑的清晰性。

内容的提问来源于stack exchange,提问作者Leonardo de Paula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:47:38