Home > Mobile >  Problem with simple Inheritance for class representing arithmetic expressions
Problem with simple Inheritance for class representing arithmetic expressions

Time:11-17

I have a problem implementing a simple class hierarchy with arithmetic expressions.

TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

and the same for the other operations, addition, subtraction, division, etc.

My code:

from abc import ABC, abstractmethod

class Wyrazenie(ABC):
    # @abstractmethod
    def Oblicz(self):
        pass


class Operator(Wyrazenie):
    w1 = Wyrazenie()
    w2 = Wyrazenie()
    def __init__(self, wy1, wy2):
        self.w1 = wy1
        self.w2 = wy2
    #def Oblicz(self) -> int:
    #    pass


class Zmienna(Wyrazenie):
    zmienna=""
    slownik={}
    def __init__(self, klucz, wartosc):
        self.slownik.update({klucz: wartosc})

    def Oblicz(self):
        return self.slownik.get(self.zmienna)


class Stala(Wyrazenie):
    wartosc=0
    def __init__(self, wartosc1):
        self.wartosc=wartosc1

    def Oblicz(self):
        return self.wartosc


class Dodaj(Operator):
    def __init__(self, wy1=None, wy2=None):
        super().__init__(wy1, wy2)

    def Oblicz(self) -> int:
        return self.w1.Oblicz()   self.w2.Oblicz()


class Odejmij(Operator):
    def __init__(self, wy1=None, wy2=None):
        super().__init__(wy1,wy2)

    def Oblicz(self) -> int:
        return self.w1.Oblicz() - self.w2.Oblicz()


class Pomnoz(Operator):
    def __init__(self, wy1=None, wy2=None):
        super().__init__(wy1,wy2)

    def Oblicz(self) -> int:
        return self.w1.Oblicz() * self.w2.Oblicz()


class Podziel(Operator):
    def __init__(self, wy1=None, wy2=None):
        super().__init__(wy1,wy2)

    def Oblicz(self) -> int:
        return self.w1.Oblicz() / self.w2.Oblicz()


z1=Zmienna("x", 4)
z2=Zmienna("y", 10)

#   4 * 10   10 - 5 = 45
wyr = Dodaj(Pomnoz(z1, Stala(10)), Odejmij(z2, Stala(5)))

wyr.Oblicz()

print("Wartosc wyrazenia=   \n")
print(wyr.Oblicz())

I don't know whether it's an issue with initializing wy1, wy2 with None or whole wrong idea of representing such expressions. I tried to rewrite it from my Java class.

CodePudding user response:

I'm not sure why you're adding so much complication before fixing something basic, but here's what's happening:

  • you call wyr.Oblicz(), which is Dodaj.Oblicz() (by the way, bad idea to name a method with capitals, it's very confusing as it looks like a class)
  • it calls self.w1.Oblicz() before trying sum the result with something else, and it is the Oblicz() of the first parameter passed to Dodaj(Pomnoz(z1, Stala(10)), Odejmij(z2, Stala(5))), so Pomnoz.Oblicz()
  • it calls self.w1.Oblicz() before trying to multiply the result with something else, and it is the first parameter of Pomnoz, i.e. zi, which is Zmienna("x", 4), so Zmienna.Oblicz()
  • it calls self.slownik.get(self.zmienna), but since self.zmienna is "" and there is no entry for "" in self.slownik, it returns None

That None is passed back and the multiplication then fails when Pomnoz.Oblicz() tries to perform it, as it cannot multiply None and an integer.

If you were using an IDE with a debugger, you could trace that yourself, by stepping into code as it's calling further functions - consider using something like PyCharm, Spyder, VSCode or any other or editor or IDE that has a debugging facility.

CodePudding user response:

I've traced your code down, and I found that the reason this error is occurring is ultimately because Zmienna.Oblicz is returning None.

The call wyr.Oblicz() is like this:

wyr (Dodaj) .Oblicz ->
  wyr.w1 (Pomnoz) .Oblicz ->
    wyr.w1.w1 (z1) (Zmienna) .Oblicz ->
      self (Zmienna) .slownik.get(self.zmienna) ->
        this call returned None

At the time slownik.get was called, slownik was a dict containing {'x': 4, 'y': 10}, and self.zmienna was an str containing "".

  • Related