De opgave van deze oefening bestaat uit relatief veel tekst. Daarom kan het handig zijn om 2 browser vensters te openen (eentje met de opgave en eentje waarin je de oplossing noteert), zodat je niet steeds moet scrollen.
Elk object van de klasseFiguur is opgebouwd uit een aantal Vormen. We beschouwen in deze oefening twee specifieke soorten vormen, namelijk rechthoeken (objecten van de klasse Rechthoek) en driehoeken (objecten van de klasse Driehoek). Omdat rechthoeken en driehoeken speciale soorten vormen zijn, erven beide klassen over van de klasse Vorm.
Programmeer de klassen Vorm, Rechthoek, Driehoek  en Figuur, volgens onderstaande richtlijnen.
'?'. __str__() levert de stringgedaante van de vorm, namelijk (naam,type) (dus naam en type, gescheiden door een komma, het geheel tussen ronde haakjes).__eq__(), waarbij 2 vormen als gelijk beschouwd worden als en slechts als ze dezelfde naam hebben__hash__() die consistent is met de __eq__()-methode die je zonet programmeerde.oppervlakte() (zonder argumenten), die de waarde 0 als resultaat oplevert.v1 = Vorm('A')
v2 = Vorm('B')
v3 = Vorm('A')
v4 = Vorm('C')
print(v1 == v2)                 #False
print(hash(v1) == hash(v2))     #False
print(v1 == v3)                 #True
print(hash(v1) == hash(v3))     #True
v = set([v1, v2, v3, v4])
print(set([str(e) for e in v])) #{'(B,?)', '(C,?)', '(A,?)'}
Rechthoek erft over van Vorm. Gebruik zoveel mogelijk de functionaliteit uit de klasse Vorm!
naam: naam van de vorm l: lengte van de rechthoek (geheel)b: breedte van de rechthoek (geheel)'R'.
    __str__() bestaat uit dezelfde uitvoer als de methode __str__() uit de klasse Vorm (met uiteraard het juiste type), gevolgd door [lenge,breedte] (lengte en breedte, gescheiden door een komma, en dit tussen vierkante haakjes.oppervlakte() levert nu de oppervlakte van de rechthoek (geheel getal). Driehoek erft over van Vorm. Gebruik ook hier zoveel mogelijk de functionaliteit uit de klasse Vorm!
naam: naam van de vorm b: basis van de driehoek (geheel)h: hoogte van de rechthoek (geheel)'D'. Verder is gegeven dat basis en hoogte niet beiden oneven zijn.
    __str__() bestaat uit dezelfde uitvoer als de methode __str__() uit de klasse Vorm (met uiteraard het juiste type), gevolgd door [basis,hoogte] (basis en hoogte, gescheiden door een komma, en dit tussen vierkante haakjes.oppervlakte() levert nu de oppervlakte van de driehoek (geheel getal, vermits basis en/of hoogte even zijn). v = Vorm('A')
r1 = Rechthoek('B', 1, 2)
r2 = Rechthoek('C', 3, 4)
d1 = Driehoek('D', 2, 6)
d2 = Driehoek('B', 3, 4)
isinstance(r1, Rechthoek) #True
isinstance(r2, Vorm)      #True
isinstance(d1, Driehoek)  #True
isinstance(d2, Vorm)      #True
print(v)  #(A,?)
print(r1) #(B,R)[1,2]
print(r2) #(C,R)[3,4]
print(d1) #(D,D)[2,6]
print(d2) #(B,D)[3,4]
print(v.oppervlakte())  #0
print(r1.oppervlakte()) #2
print(r2.oppervlakte()) #12
print(d1.oppervlakte()) #6
print(d2.oppervlakte()) #6
vormen = set([v, r1, r2, d1, d2])
print(set([str(e) for e in vormen])) #{'(C,R)[3,4]', '(A,?)', '(D,D)[2,6]', '(B,R)[1,2]'}
Vormen. Initieel is deze verzameling leeg. De Figuur wordt dan opgebouwd door telkens een Vorm toe te voegen aan de Figuur via de +=-operator.
__str__() levert een stringgedaante, die bestaat uit alle stringgedaanten van de vormen waaruit de figuur opgebouwd is, gescheiden door komma's en het geheel tussen accolades. De stringedaanten van de vormen komen in alfabetische volgorde voor (alfabetisch op vormnaam).+= heeft als effect:
        Vorm is, wordt deze vorm toegevoegd aan de verzameling vormen waaruit de figuur opgebouwd is (let op: vermits het om een verzameling gaat, en 2 vormen identiek zijn als ze identieke namen hebben, heeft deze operator geen effect als je een vorm probeert toe te voegen met een naam die al voorkomt in de figuur)'R' of 'D'oppervlakte() levert de som van de oppervlakten van alle vormen van de figuurmax_oppervlakte() levert de vorm met de grootste oppervlakte van de figuur (dus een object van de klasse Vorm of een subklasse ervan, en niet de waarde van de maximale oppervlakte). 
    Indien er meerdere vormen dezelfde maximale oppervlakte hebben, dan mag je 1 van die vormen als resultaat teruggeven.v = [Vorm(naam) for naam in ['A', 'B']]
r = [Rechthoek(naam, l, b) for (naam, l, b) in zip(['RA', 'RB'], [1, 2], [3, 4])]
d = [Driehoek(naam, b, h) for (naam, b, h) in zip(['DA', 'DB'], [2, 4], [3, 5])]
fig = Figuur()
for vorm in v + r + d:
	fig += vorm
print(fig) #{(A,?),(B,?),(DA,D)[2,3],(DB,D)[4,5],(RA,R)[1,3],(RB,R)[2,4]}
for e in [('R', 'RC', 4, 5), ('R', 'RD', 2, 7), ('D', 'DC', 2, 2), ('D', 'DD', 4, 4)]:
	fig += e
print(fig)
#{(A,?),(B,?),(DA,D)[2,3],(DB,D)[4,5],(DC,D)[2,2],(DD,D)[4,4],(RA,R)[1,3],(RB,R)[2,4],(RC,R)[4,5],(RD,R)[2,7]}
print(fig.oppervlakte())     #68
print(fig.max_oppervlakte()) #(RC,R)[4,5]