本文目录导读:

我来详细介绍如何实现一个公式运算脚本系统,我将从简单到复杂提供几种实现方案。
基础方案:使用内置函数
Python实现(最简单)
# 使用内置的eval函数(注意安全风险)
def calculate_safe(expression, variables=None):
"""安全计算表达式"""
if variables is None:
variables = {}
# 允许的数学函数和操作
allowed_names = {
'abs': abs, 'max': max, 'min': min,
'round': round, 'sum': sum,
'pow': pow, 'sqrt': lambda x: x**0.5
}
# 合并用户变量
allowed_names.update(variables)
try:
# 编译表达式
code = compile(expression, '<string>', 'eval')
# 验证代码是否为安全操作
for name in code.co_names:
if name not in allowed_names:
raise NameError(f"未允许的操作: {name}")
return eval(code, {"__builtins__": {}}, allowed_names)
except Exception as e:
return f"计算错误: {str(e)}"
# 使用示例
variables = {'x': 10, 'y': 5}
result = calculate_safe("x + y * 2", variables)
print(f"计算结果: {result}") # 输出: 20
自定义表达式解析器
使用词法分析和语法分析
import re
from enum import Enum
class TokenType(Enum):
NUMBER = 'NUMBER'
PLUS = 'PLUS'
MINUS = 'MINUS'
MULTIPLY = 'MULTIPLY'
DIVIDE = 'DIVIDE'
LPAREN = 'LPAREN'
RPAREN = 'RPAREN'
VARIABLE = 'VARIABLE'
POWER = 'POWER'
class Token:
def __init__(self, type, value):
self.type = type
self.value = value
class Lexer:
def __init__(self, text):
self.text = text
self.pos = 0
self.tokens = []
self.current_char = text[0] if text else None
def error(self):
raise Exception('非法字符')
def advance(self):
self.pos += 1
if self.pos < len(self.text):
self.current_char = self.text[self.pos]
else:
self.current_char = None
def skip_whitespace(self):
while self.current_char and self.current_char.isspace():
self.advance()
def number(self):
result = ''
while self.current_char and (self.current_char.isdigit() or self.current_char == '.'):
result += self.current_char
self.advance()
return float(result)
def variable(self):
result = ''
while self.current_char and (self.current_char.isalnum() or self.current_char == '_'):
result += self.current_char
self.advance()
return result
def tokenize(self):
while self.current_char:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char.isdigit() or self.current_char == '.':
self.tokens.append(Token(TokenType.NUMBER, self.number()))
elif self.current_char.isalpha() or self.current_char == '_':
self.tokens.append(Token(TokenType.VARIABLE, self.variable()))
elif self.current_char == '+':
self.tokens.append(Token(TokenType.PLUS, '+'))
self.advance()
elif self.current_char == '-':
self.tokens.append(Token(TokenType.MINUS, '-'))
self.advance()
elif self.current_char == '*':
self.advance()
if self.current_char == '*':
self.tokens.append(Token(TokenType.POWER, '**'))
self.advance()
else:
self.tokens.append(Token(TokenType.MULTIPLY, '*'))
elif self.current_char == '/':
self.tokens.append(Token(TokenType.DIVIDE, '/'))
self.advance()
elif self.current_char == '(':
self.tokens.append(Token(TokenType.LPAREN, '('))
self.advance()
elif self.current_char == ')':
self.tokens.append(Token(TokenType.RPAREN, ')'))
self.advance()
else:
self.error()
return self.tokens
class Parser:
def __init__(self, tokens, variables=None):
self.tokens = tokens
self.pos = 0
self.current_token = tokens[0] if tokens else None
self.variables = variables or {}
def error(self):
raise Exception('语法错误')
def eat(self, token_type):
if self.current_token and self.current_token.type == token_type:
self.pos += 1
if self.pos < len(self.tokens):
self.current_token = self.tokens[self.pos]
else:
self.current_token = None
else:
self.error()
def factor(self):
token = self.current_token
if token.type == TokenType.NUMBER:
self.eat(TokenType.NUMBER)
return token.value
elif token.type == TokenType.VARIABLE:
self.eat(TokenType.VARIABLE)
if token.value in self.variables:
return self.variables[token.value]
else:
raise Exception(f"未定义的变量: {token.value}")
elif token.type == TokenType.LPAREN:
self.eat(TokenType.LPAREN)
result = self.expr()
self.eat(TokenType.RPAREN)
return result
elif token.type == TokenType.MINUS:
self.eat(TokenType.MINUS)
return -self.factor()
def term(self):
result = self.factor()
while self.current_token and self.current_token.type in (TokenType.MULTIPLY, TokenType.DIVIDE, TokenType.POWER):
token = self.current_token
if token.type == TokenType.MULTIPLY:
self.eat(TokenType.MULTIPLY)
result *= self.factor()
elif token.type == TokenType.DIVIDE:
self.eat(TokenType.DIVIDE)
divisor = self.factor()
if divisor == 0:
raise Exception("除零错误")
result /= divisor
elif token.type == TokenType.POWER:
self.eat(TokenType.POWER)
result **= self.factor()
return result
def expr(self):
result = self.term()
while self.current_token and self.current_token.type in (TokenType.PLUS, TokenType.MINUS):
token = self.current_token
if token.type == TokenType.PLUS:
self.eat(TokenType.PLUS)
result += self.term()
elif token.type == TokenType.MINUS:
self.eat(TokenType.MINUS)
result -= self.term()
return result
def parse(self):
return self.expr()
# 使用示例
def evaluate_expression(expression, variables=None):
lexer = Lexer(expression)
tokens = lexer.tokenize()
parser = Parser(tokens, variables)
return parser.parse()
# 测试
formula = "x * (y + 2) - 5"
vars = {'x': 10, 'y': 3}
result = evaluate_expression(formula, vars)
print(f"{formula} = {result}") # 输出: 45.0
使用专业库(推荐)
sympy库
import sympy as sp
# 定义符号变量
x, y = sp.symbols('x y')
# 公式定义
formula = x**2 + 2*x*y + y**2
# 代入数值
result = formula.subs({x: 3, y: 4})
print(f"计算结果: {result}") # 输出: 49
# 公式简化
simplified = sp.simplify((x+y)**2 - (x**2 + 2*x*y + y**2))
print(f"简化结果: {simplified}") # 输出: 0
# 求导
derivative = sp.diff(formula, x)
print(f"导数: {derivative}") # 输出: 2*x + 2*y
numexpr库(高性能)
import numexpr as ne
import numpy as np
# 简单计算
result = ne.evaluate('2*3 + 4')
print(f"简单计算: {result}")
# 向量计算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
result = ne.evaluate('a * b + 10')
print(f"向量计算: {result}")
# 复杂公式
x = np.arange(10)
result = ne.evaluate('x**2 + 3*x + 1')
print(f"数组计算: {result}")
完整的公式引擎实现
import re
import math
from typing import Dict, Any, Optional
class FormulaEngine:
"""完整的公式计算引擎"""
# 内置函数映射
BUILTIN_FUNCTIONS = {
'abs': abs,
'max': max,
'min': min,
'pow': pow,
'sqrt': math.sqrt,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'log': math.log,
'log10': math.log10,
'exp': math.exp,
'ceil': math.ceil,
'floor': math.floor,
'round': round,
'pi': math.pi,
'e': math.e
}
def __init__(self):
self.variables = {}
self.custom_functions = {}
def set_variable(self, name: str, value: Any):
"""设置变量"""
self.variables[name] = value
def set_variables(self, variables: Dict[str, Any]):
"""批量设置变量"""
self.variables.update(variables)
def add_function(self, name: str, func):
"""添加自定义函数"""
self.custom_functions[name] = func
def validate_formula(self, formula: str) -> bool:
"""验证公式合法性"""
try:
# 检查括号匹配
stack = []
for char in formula:
if char == '(':
stack.append(char)
elif char == ')':
if not stack:
return False
stack.pop()
if stack:
return False
# 检查非法字符
valid_chars = r'[\w\s\+\-\*\/\(\)\.\,\^\%]'
for char in formula:
if char not in valid_chars and not char.isalpha() and not char.isdigit():
if char not in '_.':
return False
return True
except:
return False
def calculate(self, formula: str, **kwargs) -> Any:
"""计算公式"""
# 合并变量
all_vars = {**self.variables, **kwargs}
all_funcs = {**self.BUILTIN_FUNCTIONS, **self.custom_functions}
# 创建计算上下文
context = {**all_vars, **all_funcs}
try:
# 编译公式
code = compile(formula, '<string>', 'eval')
# 验证所有名称都在允许的范围内
for name in code.co_names:
if name not in context:
raise NameError(f"未定义的变量或函数: {name}")
# 安全执行
result = eval(code, {"__builtins__": {}}, context)
return result
except ZeroDivisionError:
return "错误: 除零"
except NameError as e:
return f"错误: {str(e)}"
except Exception as e:
return f"计算错误: {str(e)}"
def batch_calculate(self, formulas: Dict[str, str], **kwargs) -> Dict[str, Any]:
"""批量计算公式"""
results = {}
for name, formula in formulas.items():
results[name] = self.calculate(formula, **kwargs)
return results
# 使用示例
engine = FormulaEngine()
# 设置变量
engine.set_variable('price', 100)
engine.set_variable('tax_rate', 0.08)
# 添加自定义函数
def discount(price, rate):
return price * (1 - rate)
engine.add_function('discount', discount)
# 计算公式
formulas = {
'total_price': 'price * (1 + tax_rate)',
'discount_price': 'discount(price, 0.2)',
'monthly_payment': 'total_price / 12 + 10',
'complex': 'sqrt(price) + pow(tax_rate, 2)'
}
results = engine.batch_calculate(formulas)
for name, result in results.items():
print(f"{name}: {result}")
安全建议和最佳实践
完整的公式脚本系统
import ast
import operator
from typing import Any, Dict
class SafeFormulaEvaluator:
"""安全公式计算器"""
# 允许的操作符
OPERATORS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
ast.USub: operator.neg,
ast.Mod: operator.mod
}
def __init__(self):
self.variables = {}
self.functions = {}
# 注册基本数学函数
self.register_math_functions()
def register_math_functions(self):
"""注册数学函数"""
import math
math_funcs = [
'abs', 'max', 'min', 'pow', 'sqrt',
'sin', 'cos', 'tan', 'log', 'log10',
'exp', 'ceil', 'floor', 'round'
]
for func_name in math_funcs:
if hasattr(math, func_name):
self.functions[func_name] = getattr(math, func_name)
elif func_name == 'abs':
self.functions[func_name] = abs
elif func_name in ('max', 'min'):
self.functions[func_name] = globals()[func_name]
def evaluate(self, expression: str, variables: Dict[str, Any] = None) -> Any:
"""安全评估表达式"""
if variables:
self.variables.update(variables)
try:
tree = ast.parse(expression, mode='eval')
return self._evaluate_node(tree.body)
except Exception as e:
raise ValueError(f"计算公式失败: {str(e)}")
def _evaluate_node(self, node):
"""评估AST节点"""
if isinstance(node, ast.Expression):
return self._evaluate_node(node.body)
elif isinstance(node, ast.Constant):
return node.value
elif isinstance(node, ast.Name):
if node.id in self.variables:
return self.variables[node.id]
elif node.id in self.functions:
return self.functions[node.id]
else:
raise NameError(f"未定义: {node.id}")
elif isinstance(node, ast.BinOp):
left = self._evaluate_node(node.left)
right = self._evaluate_node(node.right)
op = self.OPERATORS[type(node.op)]
return op(left, right)
elif isinstance(node, ast.UnaryOp):
operand = self._evaluate_node(node.operand)
op = self.OPERATORS[type(node.op)]
return op(operand)
elif isinstance(node, ast.Call):
func = self._evaluate_node(node.func)
args = [self._evaluate_node(arg) for arg in node.args]
if callable(func):
return func(*args)
raise TypeError(f"不可调用的对象: {func}")
elif isinstance(node, ast.List):
return [self._evaluate_node(item) for item in node.elts]
elif isinstance(node, ast.Tuple):
return tuple(self._evaluate_node(item) for item in node.elts)
else:
raise NotImplementedError(f"不支持的节点类型: {type(node).__name__}")
# 使用示例
evaluator = SafeFormulaEvaluator()
# 设置变量
variables = {
'x': 10,
'y': 20,
'z': 5
}
# 测试各种公式
test_formulas = [
"x + y",
"x * y - z",
"sqrt(x**2 + y**2)",
"sin(x) + cos(y)",
"max(x, y, z)",
"(x + y) / z + pow(x, 2)"
]
for formula in test_formulas:
try:
result = evaluator.evaluate(formula, variables)
print(f"{formula} = {result}")
except Exception as e:
print(f"错误: {formula} -> {str(e)}")
高级特性实现
条件表达式和循环
class AdvancedFormulaEngine:
"""高级公式引擎,支持条件和循环"""
def __init__(self):
self.variables = {}
self.functions = {}
self.condition_ops = {
'==': operator.eq,
'!=': operator.ne,
'<': operator.lt,
'>': operator.gt,
'<=': operator.le,
'>=': operator.ge,
'and': lambda x, y: x and y,
'or': lambda x, y: x or y,
'not': operator.not_
}
def evaluate(self, expression, variables=None):
if variables:
self.variables.update(variables)
return self._parse_and_execute(expression)
def _parse_and_execute(self, expr):
# 处理条件表达式
if ' if ' in expr and ' else ' in expr:
# 三元运算符
pattern = r'^(.+?)\s+if\s+(.+?)\s+else\s+(.+)$'
match = re.match(pattern, expr)
if match:
true_val = match.group(1)
condition = match.group(2)
false_val = match.group(3)
if self._parse_and_execute(condition):
return self._parse_and_execute(true_val)
else:
return self._parse_and_execute(false_val)
# 使用安全评估
return self._safe_eval(expr)
def _safe_eval(self, expression):
"""安全评估表达式"""
# 简化实现,实际应考虑所有安全因素
allowed_context = {
**self.variables,
**self.functions,
**self.condition_ops
}
try:
return eval(expression, {"__builtins__": {}}, allowed_context)
except Exception as e:
raise ValueError(f"计算错误: {str(e)}")
# 使用示例
engine = AdvancedFormulaEngine()
engine.variables = {'x': 15, 'y': 10, 'z': 8}
formula = "x if x > y else y"
result = engine.evaluate(formula)
print(f"条件结果: {result}") # 输出: 15
实现公式运算脚本的主要方法:
- 简单场景:使用
eval()或numexpr库 - 中等复杂度:自定义词法解析器
- 专业需求:使用
sympy、numexpr等专业库 - 完整系统:构建安全的公式引擎
选择建议:
- 快速原型:使用 Python 的
eval()(注意安全) - 生产环境:使用
numexpr或自定义解析器 - 科学计算:使用
sympy - 高性能需求:使用
numexpr或编译为字节码
记得始终考虑安全性,对用户输入的公式进行验证和限制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播