import ast
import operator

funca = "aa / dd * 100"
funcb = "(bb + cc )/100"

abc = 10
bbc = 305
ddc = 65
ccc = 1000

def safe_eval(expr, variables):
    """安全计算数学表达式"""
    # 只允许的运算符
    allowed_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.UAdd: operator.pos
    }
    
    def _eval(node):
        if isinstance(node, ast.Num):
            return node.n
        elif isinstance(node, ast.Name):
            if node.id in variables:
                return variables[node.id]
            else:
                raise NameError(f"变量 '{node.id}' 未定义")
        elif isinstance(node, ast.BinOp):
            if type(node.op) not in allowed_operators:
                raise TypeError(f"不允许的操作符: {type(node.op)}")
            return allowed_operators[type(node.op)](_eval(node.left), _eval(node.right))
        elif isinstance(node, ast.UnaryOp):
            if type(node.op) not in allowed_operators:
                raise TypeError(f"不允许的操作符: {type(node.op)}")
            return allowed_operators[type(node.op)](_eval(node.operand))
        else:
            raise TypeError(f"不支持的表达式类型: {type(node)}")
    
    try:
        tree = ast.parse(expr, mode='eval')
        return _eval(tree.body)
    except Exception as e:
        raise ValueError(f"表达式计算错误: {e}")

def calculate_metrics(metrics_dict, calculate_func):
    """计算指标 - 安全版本"""
    print(f"计算表达式: {calculate_func}")
    result = safe_eval(calculate_func, metrics_dict)
    return result

# 使用类来封装更优雅
class MetricCalculator:
    def __init__(self):
        self.metrics = {}
    
    def add_metric(self, name, value):
        self.metrics[name] = value
    
    def calculate(self, expression):
        # 小数保留2位
        result = safe_eval(expression, self.metrics)
        return round(result, 2)
    
    def __str__(self):
        return f"当前指标: {self.metrics}"
    
def test():
    funca = "aa / dd * 100"
    funcb = "(bb + cc )/100"
    abc = 10
    bbc = 305
    ddc = 65
    ccc = 1000
    metric_definition_list = {
        "aa": abc,
        "bb": bbc,
        "cc": ccc,
        "dd": ddc
    }
    result1 = calculate_metrics(metric_definition_list, funca)
    print(f"结果1: {result1}")
    result2 = calculate_metrics(metric_definition_list, funcb)
    print(f"结果2: {result2}")
    # 使用方法2：面向对象（更优雅）
    calculator = MetricCalculator()
    calculator.add_metric("aa", abc)
    calculator.add_metric("bb", bbc) 
    calculator.add_metric("cc", ccc)
    calculator.add_metric("dd", ddc)
    print(calculator)
    result3 = calculator.calculate(funca)
    print(f"结果3: {result3}")