def _evaluate_expression(self, expr):
        """Evaluate an :class:`.Expression` using :meth:`_get_value`."""
        def cast_value(v):
            # Convert Decimal to Fraction to allow successful multiplication
            # by either float (most solvers) or Fraction (exact solver).
            # Multiplying Fraction and float results in a float, and
            # multiplying Fraction and Fraction result in Fraction, which are
            # exactly the types of results we want.
            if isinstance(v, Decimal):
                return Fraction(v)
            return v

        total = cast_value(expr.offset)
        for var, value in expr.values():
            value = cast_value(value)
            if not isinstance(var, Product):
                total += self._get_value(var) * value
            else:
                total += reduce(
                    operator.mul, (self._get_value(v) for v in var), value)
        return total
Evaluate an :class:`.Expression` using :meth:`_get_value`.