error w zadaniu z typem

0

treść zadania: Wykorzystując klasy z poprzedniego ćwiczenia stwórz klasy opisujące czworościan, sześcian i 'piramidę' jako listy figur foremnych tworzących ściany tych brył - niech w konstruktorze każda z klas tworzy listę ściany zawierającą odpowiednie obiekty. Parametrem konstruktora będzie bok każdej ściany (figury są foremne, więc wszystkie bedą miały taką samą długosć swoich boków).

Niech klasy brył też pochodzą od klasy Kształt - dzięki temu odziedziczą pole nazwa. Ale muszą nadpisać metodę abstrakcyjną pole. Ta metoda będzie identyczna w każdej z klas (polega na zsumowaniu pól wszystkich ścian z listy). Zatem moglibyśmy stworzyć nadklasę Bryła, która w zasadzie tu powinnna być zastosowana, bo nasze klasy są ze sobą powiązane. Jednakże dla przećwiczenia innego podejścia stworzymy mixin - w praktyce stosowany dla klas niepowiązanych ze sobą. mixin jest prostą klasą (nawet bez konstruktora) zawierającą tylko jedną metodę lub kilka metod 'wstrzykiwanych' do innej klasy. W naszym wypadku 'wstrzykniemy' metodę pole (którą tu zdefiniujemy) poprzez to, że nasze klasy będą dziedziczyły po mixin-ie.

'Przy okazji' uzyskamy wielodziedziczenie, przy czym w tym wypadku ważna jest kolejność - klasa Kształt wymaga metody pole, a więc najpierw należy dziedziczyć po mixin-ie (aby 'wstrzyknąć' pole), a potem po Kształt.

W main należy stworzyć listę figur zawierającą przykładowe obiekty każdej z brył i w pętli wypisać nazwy brył oraz ich pola.

mój kod:


from abc import ABC, abstractmethod
import math

class mixin(ABC):
    
    @abstractmethod
    def pole(self):
        pass

class Kształt(mixin):
    def __init__(self, nazwa):
        self.__nazwa = nazwa
        
    @property
    def nazwa(self):
        return self.__nazwa
    
        
class Trójkąt(Kształt):
    def __init__(self, nazwa, bok_a, bok_b, bok_c):
        super().__init__(nazwa)
        self.bok_a = bok_a
        self.bok_b = bok_b
        self.bok_c = bok_c

    def pole(self):
        s = (self.bok_a + self.bok_b + self.bok_c) / 2
        area = math.sqrt(s * (s - self.bok_a) * (s - self.bok_b) * (s - self.bok_c))
        return area
        
class Prostokąt(Kształt):
    def __init__(self, nazwa,bok_a, bok_b):
        super().__init__(nazwa)
        self.bok_a = bok_a
        self.bok_b = bok_b
    
    def pole(self):
        return self.bok_a*self.bok_b

class Kwadrat(Prostokąt):
    def __init__(self, nazwa,bok_a):
        super().__init__(nazwa,bok_a,bok_a)
        
    def pole(self):
        return super().pole()
        
class TrojkatRownoboczny(Trójkąt):
    def __init__(self,nazwa, bok_a):
        super().__init__(nazwa, bok_a, bok_a, bok_a)
    
    def pole(self):
        return super().pole()
        
class Czworoscian(Kształt):
    def __init__(self, nazwa, bok):
        super().__init__(nazwa)
        self.sciany = [TrojkatRownoboczny("trojkat", bok),
                       TrojkatRownoboczny("trojkat", bok),
                       TrojkatRownoboczny("trojkat", bok),
                       TrojkatRownoboczny("trojkat", bok)]
        
    def pole(self):
        return sum(sciana.pole() for sciana in self.sciany)
        
class Szescian(Kształt):
    def __init__(self, nazwa, bok):
        super().__init__(nazwa)
        self.sciany = [Kwadrat("kwadrat",bok),
                       Kwadrat("kwadrat",bok),
                       Kwadrat("kwadrat",bok),
                       Kwadrat("kwadrat",bok),
                       Kwadrat("kwadrat",bok),
                       Kwadrat("kwadrat",bok)]
        
    def pole(self):
        return sum(sciana.pole() for sciana in self.sciany)
        
        
class Piramida(Kształt):
    def __init__(self, nazwa, tr, bok):
        super().__init__(nazwa)
        self.sciany = [Kwadrat("kwadrat",bok),
                       TrojkatRownoboczny("trojkat",bok),
                       TrojkatRownoboczny("trojkat",bok),
                       TrojkatRownoboczny("trojkat",bok)]
    def pole(self):
        return sum(sciana.pole for sciana in self.sciany)

def main():
    
    t = Trójkąt("trojkat",1,2,2)
    kw = Kwadrat("kwadrat",4)
    tr = TrojkatRownoboczny("trojkatrownoboczny",6)
    cz = Czworoscian("czworoscian", tr)
    sz = Szescian("kwadrat",kw)
    p = Piramida("piramida", tr, kw)
    
    lista = [t,kw,tr,cz,sz,p]

       
    for figura in lista:
        print(figura.nazwa, figura.pole())

main()
        
     
    

wyświetla błąd:

trojkat 0.9682458365518543
kwadrat 16
trojkatrownoboczny 15.588457268119896
Traceback (most recent call last):
  File "/home/main.py", line 104, in <module>
    main()
  File "/home/main.py", line 102, in main
    print(figura.nazwa, figura.pole())
  File "/home/main.py", line 63, in pole
    return sum(sciana.pole() for sciana in self.sciany)
  File "/home/main.py", line 63, in <genexpr>
    return sum(sciana.pole() for sciana in self.sciany)
  File "/home/main.py", line 52, in pole
    return super().pole()
  File "/home/main.py", line 27, in pole
    s = (self.bok_a + self.bok_b + self.bok_c) / 2
TypeError: unsupported operand type(s) for +: 'TrojkatRownoboczny' and 'TrojkatRownoboczny'

nie mogę dojść do tego co jest błędem, mógłby ktoś doradzić?

5

Do czworościanu przekazujesz bok w postaci instancji TrojkatRownoboczny. Klasa trojkata nie ma zdefiniowanego __add__ i innych magicznych metod arytmetycznych.

Poza tym nazwa mixin dla ABC jest myląca. Powinna brzmieć Figura

0

dopisałem tak, ale nadal te same błędy. Jak to zrobić poprawnie?


class Kwadrat(Prostokąt):
    def __init__(self, nazwa,bok_a):
        super().__init__(nazwa,bok_a,bok_a)
        
    def __add__(self,other):
        pole1 = self.pole()
        pole2 = other.pole()
        return pole1+pole2
        
        
class TrojkatRownoboczny(Trójkąt):
    def __init__(self,nazwa, bok_a):
        super().__init__(nazwa, bok_a, bok_a, bok_a)
        
    def __add__(self,other):
        pole1 = self.pole()
        pole2 = other.pole()
        return pole1+pole2


0

Jak piszesz dodawanie dla obiektów, to je jakoś dodaj, (z drugiej strony, jaki ma sens dodawanie trójkątów!?!),a nie wołaj tam pole/

2
def __add__(self,other):
    pole1 = self.pole()
    pole2 = other.pole()
    return pole1+pole2

Zwracasz tutaj inta a nie obiekt co przy kolejnej iteracji będzie skutkowało próbą dodania inta do obiektu klasy i dostaniesz coś w stylu TypeError: unsupported operand type(s) for +: 'int' and 'TrojkatRownoboczny'.

Powinieneś zwrócić

return TrojkatRownoboczny(self.nazwa, pole1+pole2)

To samo tyczy się całej reszty funkcji arytmetycznych. Musisz jeszcze zaimplementować __truediv__, __mul__, __sub__

No i generalnie zacznij używać typowania, bo sam nie wiesz co przekazujesz :) Ide wtedy dużo Ci podpowie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1