Search code examples
pythonpython-2.7sympypython-object

How to extend Symbol class in sympy?


I’m having trouble extending the Symbol class in sympy. It could be a result of something with class extensions in general, or it might also be an issue with this specific “Symbol” class.

I want to extend the Symbol class to have an additional attribute called “boolean_attr” which is a True/False attribute. This simulates what I’m trying to do:

class A(object):  # This simulates what the "Symbol" class is in sympy

    __slots__ = ['a']

    def __init__(self, a):
        self.a = a


# this simulates my extension to add a property
class B(A):

    def __init__(self, boolean_attr):
        self. boolean_attr = boolean_attr

And that seems to work as expected:

my_B = B(False)
print my_B.boolean_attr
>>>> False

So, when I try this in Sympy this is what I do:

from sympy.core.symbol import Symbol
class State(Symbol):

    def __init__(self, boolean_attr):
        self.boolean_attr = boolean_attr

But this doesn’t work:

TypeError: name should be a string, not <type 'bool'>

How do I add an attribute to the Symbol class in sympy? Thanks.

(Additionally, I should mention that this might be an xy problem without me knowing it. I want to know how to add an attribute to a class, and my question assumes that extending the class is the best way to do that. If this is an incorrect assumption, please let me know)


Solution

  • I was able to fix this by more carefully examining the Symbol class in SymPy. The __new__ method takes as input a string called 'name', and so we at least need that in the call to Super in the subclass:

    from sympy.core.symbol import Symbol
    class State(Symbol):
        def __init__(self, name, boolean_attr):
            self.boolean_attr = boolean_attr
            super(State, self).__init__(name)
    

    Furthermore, without using the keyword arguments, this fails: State('x', True) with the error TypeError: __new__() takes exactly 2 arguments (3 given) (https://pastebin.com/P5VmD4w4)

    However if I use a keyword argument, then it appears to work:

    x = State('x', boolean_attr=True)