Skip to content
Advertisement

How to pass args to sympy.lambdify

This is a more precise version of this question where the comments said my minimal reproducible code was too minimal, so with more information:

I want to evaluate an Expression without having to pass the symbols along separately. My current workaround is this:

from sympy import Symbol, lambdify


def evaluate_expr(expr):
    lambdified = lambdify(tuple(expr.free_symbols), expr)
    return lambdified(*[i.value for i in expr.free_symbols])


class symbol_x(Symbol):
    def __new__(cls, symbol, value):
        obj = Symbol.__new__(cls, symbol)
        obj.value = value
        return obj

x = symbol_x('x', 2)
y = symbol_x('y', 3)

value = evaluate_expr(x / y)
print(value)

This works. My problem is that expr.free_symbols is a set (which doesn’t maintain order), so casting it to a tuple might create unexpected bugs. What would be the correct way of evaluating this expression?

Advertisement

Answer

You need to sort the free symbols according to some reproducible logic, like sorting by name:

def evaluate_expr(expr):
    fs = sorted(expr.free_symbols, key=lambda t: t.name)
    lambdified = lambdify(fs, expr)
    return lambdified(*[i.value for i in fs])

Edit for explanation:

The problem is that expr.free_symbols returns a set. lambdify requires a list. In Python, the conversion from a set to a list is non-deterministic. For example, say you have a set {a, b}. When you convert it to a list you can either have [a, b] or [b, a].

To fix this behavior, we can use sorted to sort the free symbols alphabetically.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement