如何在Python链式运算函数中保持正确的数学运算优先级?
问题根因
你当前的实现是运算左结合立即求值,所有运算符优先级完全相同,从左到右依次计算,所以1 + 2 * 10会被计算为(1+2)*10=30,不符合先乘除后加减的数学运算规则。
解决方案
可以在保留原调用方式、纯函数式风格的前提下,改为先缓存所有运算序列,遇到=时再按优先级求值:
from functools import reduce def calc(expr): # 首次调用传入数字时初始化运算序列 if isinstance(expr, (int, float)): expr = [expr] return lambda op: { '+': lambda b: calc(expr + ['+', b]), '-': lambda b: calc(expr + ['-', b]), '*': lambda b: calc(expr + ['*', b]), '/': lambda b: calc(expr + ['/', b]), '=': (lambda: # 第二步:计算仅含加减的表达式 (lambda mid: mid[0] + sum((b if o == '+' else -b) for o, b in zip(mid[1::2], mid[2::2]))) ( # 第一步:优先计算所有乘除,生成仅含加减的中间序列 reduce( lambda acc, item: acc[:-1] + [acc[-1] * item[1]] if item[0] == '*' else acc[:-1] + [acc[-1] / item[1]] if item[0] == '/' else acc + [item[0], item[1]], zip(expr[1::2], expr[2::2]), [expr[0]] ) ) )() }[op]
验证效果
print(calc(1)('+')(2)('*')(10)('=')) # 输出 21,符合预期
实现说明
- 全程无可变状态,每次调用都生成新的运算序列,符合纯函数式设计要求
- 原调用接口完全不变,不需要修改上层调用逻辑
- 遇到
=才触发求值,求值时先遍历所有运算符完成乘除运算,再处理加减运算,符合标准数学优先级规则
内容的提问来源于stack exchange,提问作者mama
相关产品推荐
相关产品推荐

