2

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)

makansij
  • 9,303
  • 37
  • 105
  • 183

2 Answers2

1

Try the following code, it works for me on python 3.

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

Python 2 code :

from sympy.core.symbol import Symbol
class State(Symbol):
    def __init__(self, boolean_attr):
        self.boolean_attr = boolean_attr
        super(State, self).__init__()
LazyCoder
  • 1,267
  • 5
  • 17
  • Nice! thanks. However I'm using python2.7, any solution in 2.7? and can you articulate the difference? i.e. is there any reason it works with new style classes and not old-style? (I'm guessing that's the reason for the difference but please tell me if I'm wrong) – makansij Jul 26 '19 at 23:59
  • 1
    Did you try the above in python 2.7? Was there any error? – LazyCoder Jul 27 '19 at 00:00
  • @SANTOSHKUMARDESAI Your answer is clearly incorrect since for the inheritance to work you must call the parent's constructor through `super()` – eyllanesc Jul 27 '19 at 00:02
  • Of course, we need to add ```super()```, but it doesn't give an error right? I was only debugging the problem at hand. – LazyCoder Jul 27 '19 at 00:03
  • It didn't work for me in 2.7 - I got the same error that I showed in the question. – makansij Jul 27 '19 at 00:03
  • @SANTOSHKUMARDESAI With your answers you are not using inheritance, and just the question is to preserve the inheritance without generating the error. – eyllanesc Jul 27 '19 at 00:04
  • @Sother Use the correct tags, if you are using python2.7 then use that tag. Do not use or abuse other tags like python3 – eyllanesc Jul 27 '19 at 00:06
  • 1
    It is in the tags as far as I can see. Do you see it in the tags? – makansij Jul 27 '19 at 00:07
  • @SANTOSHKUMARDESAI just by calling `super()` you are not calling the construntor, you have to use `super().__init__()`. Do you know what inheritance is and how it is used in python? – eyllanesc Jul 27 '19 at 00:08
  • @Sother I deleted the python2.7 and python3 tags since the rule states that if the OP uses tags of different versions then the version is not interested (except for certain occasions that it is not yours), now I have added it because you pointed out in a previous comment is that you want the solution for python2.7 – eyllanesc Jul 27 '19 at 00:10
  • Not required in python 3 AFAIK. python 2 requires it specifically. Of course, if arguments have to be passed, the story is different. – LazyCoder Jul 27 '19 at 00:10
  • @Sother Anywho, I've tested this on https://live.sympy.org/, seems to work fine If you have any specific error, please include the driver code for testing. – LazyCoder Jul 27 '19 at 00:14
  • 1
    Guys, please continue your one on one discussion in chat. – makansij Jul 27 '19 at 00:16
  • @LazyCoder, this solution is still giving me this error: `TypeError: name should be a string, not ` – makansij Jul 29 '19 at 17:13
  • 1
    Complete stacktrace please, you could link to pastebin of course – LazyCoder Jul 30 '19 at 06:02
0

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)

makansij
  • 9,303
  • 37
  • 105
  • 183
  • I would love an explanation for why the keyword argument is necessary – makansij Jul 31 '19 at 02:08
  • There is a similar answer to this question here: https://stackoverflow.com/questions/46021227/possible-to-add-descriptions-to-symbols-in-sympy – makansij Aug 02 '19 at 21:33