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 isDodaj.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 theOblicz()
of the first parameter passed toDodaj(Pomnoz(z1, Stala(10)), Odejmij(z2, Stala(5)))
, soPomnoz.Oblicz()
- it calls
self.w1.Oblicz()
before trying to multiply the result with something else, and it is the first parameter ofPomnoz
, i.e.zi
, which isZmienna("x", 4)
, soZmienna.Oblicz()
- it calls
self.slownik.get(self.zmienna)
, but sinceself.zmienna
is""
and there is no entry for""
inself.slownik
, it returnsNone
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 ""
.