1

Say I have a container class containing some numeric value:

class Container:
    def __init__(self, value):
        self.value = value

I would like to give those Containers to a lambdified sympy expression and as a result get a new Container:

import sympy as sp
a = Container(1)
b = Container(-0.5)
x, y = sp.symbols("x y")
f = sp.lambdify((x, y), sp.atan(x)**-1*sp.pi*10 - 1/y)
result = f(a, b) # result should be a Container with value 42

Now I actually don't mind writing some wrapper around f that unpacks and packs the values, but the problem occurs here:

Like in Numpy, I also want it to be able to handle lists or lists mixed with values:

a = Container(-47)
b = Container(19)
c = [Container(0), Container(1), Container(2), Container(3), Container(4)]
x, y, z = sp.symbols("x y z")
f = sp.lambdify((x, y, z), z**4 + x/6*z**3 + y*z**2 + (x-2*y)/6*z + 3)
result = f(a, b, c) # should be a list of Containers with values 3, 1, 4, 1 and 5

What is an elegant way to achieve this?

Edit

I already wrote a wrapper function around lambdify that unpacks the values before applying the sympy expression and packs up the result, but it involves checking whether the type of an argument is a list or a Container, which is against the whole duck-typing philosophy of Python. My actual question: is there a more pythonic way to do this that doesn't involve ugly type-checking?

Safron
  • 802
  • 1
  • 11
  • 23
  • Like `numpy`, you could define all the necessary magic methods in your `Container` class. For comparison, `c = Container([0, 1, 2, 3, 4])` would work better; the class would also provide the definition of, for example, `Container(x) * Container(y)` when `x` and/or `y` are lists instead of scalars. – chepner Oct 25 '17 at 15:41
  • That would be a solution, but I'd rather not tackle the enormous task of implementing every math function that exist just to make sure every sympy expression will work. See my edit for the direction in which I'm thinking. – Safron Oct 25 '17 at 16:03
  • 1
    The `sympify` function might help. I note that you can go in one direction by adding a `_sympy_` method to `Container` that simply returns `self.value`. I'm not sure if `sympy` provides a way to automatically promote the result of a calculation back to a `Container`. – chepner Oct 25 '17 at 16:35

0 Answers0