Проблема с простым наследованием для класса, представляющего арифметические выражения

#python #abstract-class #multiple-inheritance #abstract-methods

Вопрос:

У меня проблема с реализацией простой иерархии классов с арифметическими выражениями.

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

и то же самое для других операций, сложения, вычитания, деления и т. Д.

Мой код:

 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) -gt; 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) -gt; 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) -gt; 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) -gt; 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) -gt; 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())  

Я не знаю , является ли это проблемой с инициализацией wy1 , wy2 с None или с совершенно неправильной идеей представления таких выражений. Я попытался переписать его из своего класса Java.

Ответ №1:

Я не уверен, почему вы добавляете так много сложностей, прежде чем исправить что-то основное, но вот что происходит:

  • вы вызываете wyr.Oblicz() , что Dodaj.Oblicz() (кстати, плохая идея называть метод заглавными буквами, это очень сбивает с толку, так как он выглядит как класс)
  • он вызывает self.w1.Oblicz() перед попыткой суммировать результат с чем-то другим, и это Oblicz() первый переданный параметр Dodaj(Pomnoz(z1, Stala(10)), Odejmij(z2, Stala(5))) , так что Pomnoz.Oblicz()
  • он вызывает self.w1.Oblicz() , прежде чем пытаться умножить результат на что-то другое , и это первый параметр Pomnoz , т. Е. zi , который таков Zmienna("x", 4) Zmienna.Oblicz()
  • он вызывает self.slownik.get(self.zmienna) , но так self.zmienna как есть "" и нет записи для "" входа self.slownik , он возвращается None

Это None передается обратно, и затем умножение завершается неудачей при Pomnoz.Oblicz() попытке выполнить его, так как оно не может умножаться None и на целое число.

Если вы использовали IDE с отладчиком, вы могли бы отследить это самостоятельно, войдя в код, когда он вызывает дополнительные функции — подумайте об использовании чего-то вроде PyCharm, Spyder, VSCode или любого другого редактора или IDE, у которого есть средство отладки.

Ответ №2:

Я проследил ваш код и обнаружил, что причина возникновения этой ошибки в конечном счете заключается в том, что Zmienna.Oblicz возвращается None .

Звонок wyr.Oblicz() такой:

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

В то время slownik.get назывался, slownik был dict {'x': 4, 'y': 10} содержателем и self.zmienna был str "" содержателем .