关于实现NaryExpression、MinExpression、MaxExpression类的技术求助
First, we'll define the base Expression abstract class, then implement the three required classes inheriting from it, along with helper classes for numeric literals and binary operations to match your sample output.
Base Expression Class
Use the abc module to enforce abstract methods for all required functionality:
from abc import ABC, abstractmethod from typing import List, Set, Union class Expression(ABC): @abstractmethod def __init__(self, operands: List['Expression']): pass @abstractmethod def __str__(self) -> str: pass @abstractmethod def eval(self) -> Union[int, float]: pass @abstractmethod def occuring_numbers(self) -> Set[Union[int, float]]: pass
NaryExpression Implementation
This generic n-ary class handles shared logic for Min/Max expressions, reducing code duplication:
class NaryExpression(Expression): def __init__(self, operands: List[Expression]): self.operands = operands def __str__(self) -> str: operand_strs = ", ".join(str(op) for op in self.operands) return f"{self.operator_name}({operand_strs})" def occuring_numbers(self) -> Set[Union[int, float]]: numbers = set() for op in self.operands: numbers.update(op.occuring_numbers()) return numbers @property @abstractmethod def operator_name(self) -> str: pass
MinExpression & MaxExpression
These subclasses override only the operator name and evaluation logic:
class MinExpression(NaryExpression): @property def operator_name(self) -> str: return "min" def eval(self) -> Union[int, float]: return min(op.eval() for op in self.operands) class MaxExpression(NaryExpression): @property def operator_name(self) -> str: return "max" def eval(self) -> Union[int, float]: return max(op.eval() for op in self.operands)
Helper Classes for Sample Output
Add classes to represent numeric literals and binary operations (like *, /, -):
class NumberExpression(Expression): def __init__(self, value: Union[int, float]): self.value = value def __str__(self) -> str: return f"({self.value})" def eval(self) -> Union[int, float]: return self.value def occuring_numbers(self) -> Set[Union[int, float]]: return {self.value} class BinaryExpression(Expression): def __init__(self, left: Expression, right: Expression): self.left = left self.right = right def __str__(self) -> str: return f"({str(self.left)} {self.operator} {str(self.right)})" def occuring_numbers(self) -> Set[Union[int, float]]: return self.left.occuring_numbers().union(self.right.occuring_numbers()) @property @abstractmethod def operator(self) -> str: pass class MultiplyExpression(BinaryExpression): @property def operator(self) -> str: return "*" def eval(self) -> Union[int, float]: return self.left.eval() * self.right.eval() class DivideExpression(BinaryExpression): @property def operator(self) -> str: return "/" def eval(self) -> Union[int, float]: return self.left.eval() / self.right.eval() class SubtractExpression(BinaryExpression): @property def operator(self) -> str: return "-" def eval(self) -> Union[int, float]: return self.left.eval() - self.right.eval()
Example Usage
Recreate your sample scenario and generate the expected output:
# Build nested expressions expr1 = MultiplyExpression(MultiplyExpression(NumberExpression(3), NumberExpression(3)), NumberExpression(3.14)) expr2 = DivideExpression(NumberExpression(1000), NumberExpression(3)) expr3 = SubtractExpression(NumberExpression(1000), NumberExpression(2)) min_expr = MinExpression([expr1, expr2, expr3]) # Generate formatted output result = min_expr.eval() numbers = sorted(min_expr.occuring_numbers()) print(f"{min_expr} = {result:.2f}, with numbers {{{', '.join(map(str, numbers))}}}")
Expected Output
min(((3) * (3)) * (3.14), (1000) / (3), (1000) - (2)) = 28.26, with numbers {2, 3, 3.14, 1000}
Key Details
- Recursive evaluation: Each
eval()method computes nested expressions first before calculating the final result. - Set-based number collection:
occuring_numbers()uses set union to avoid duplicate values from nested expressions. - Modular design: Shared logic lives in parent classes, making Min/Max implementations concise.
内容的提问来源于stack exchange,提问作者marlene

