@rejes: Das `datetime`-Modul wird importiert aber nicht verwendet. Dafür wird in `Presentation.change_date` versucht auf ein nicht vorhandenes `datetime`-Attribut zuzugreifen. An der Stelle müsste man dann schon mal Anmerken, das man Programme entwickelt, und nicht einmal alles komplett runterschreibt und *dann* erst das erste mal überhaupt etwas von dem Code ausführt. Immer eine Funktionionalität nach der anderen und jedes mal *testen* ob das was man da gerade geschrieben hat überhaupt funktioniert. Falls nicht macht es keinen Sinn mit der nächsten Funktionionalität weiter zu machen, die vielleicht sogar auf dem nicht-funktionierenden Code aufbaut. Denn dann wird die ja zwangsläufig auch nicht funktionieren. Erst ganz zum Schluss alle Fehler zu suchen kann zu einer sehr frustrierenden Erfahrung werden. Besonders ärgerlich ist es in solchen Fällen dann wenn sich herausstellt das die bereits geschriebene Lösung so nicht funktionieren kann, und man grössere Teile umschreiben muss.
Der Kommentar ``# constructor`` im Klassenkörper von `ResearchGroup` ist falsch. Und auch den zur `__init__()`-Methode zu verschieben wäre falsch, denn auch die ist kein Konstruktor sondern initialisiert ein zu dem Zeitpunkt bereits vorhandenes Objekt. Der Konstruktor heisst in Python `__new__()` und da gibt es nur *ganz* selten Gründe den selbst zu implementieren, also den von `object` zu überschreiben. Das macht man nur wenn man ewtas aussergewöhnliches, ”magisches” tun möchte.
Der Kommentar zur ”konstante[n] Variable” ist widersinnig. Entweder Konstante, oder Variable. Konstanten kennzeichnet man in Python auch nicht mit Kommentaren, die man ja nur an der Stelle sieht wo die Konstante definiert wird, sondern dadurch das der Name KOMPLETT_GROSS geschrieben wird. Dann sieht man auch an den Stellen wo die Konstante *verwendet* wird, das es keine Variable ist, sondern ein konstanter Wert. Dann kann auch der Kommentar entfallen.
Variablen haben auf Klassen nichts zu suchen. Es gibt nur ganz wenige Fälle in denen die Sinn machen, hier sehe ich keinen. Im Gegenteil die sind soweit ich das sehe falsch. `head` und `name` sind Attribute des Exemplars und da gehört auch `members` hin.
`cost` scheint eine Konstante zu sein‽ Macht aber bei dem gezeigten Code überhaupt keinen Sinn. Das wäre eher ein Property in dem die Kosten zum Beispiel aus einem fixen Anteil und den Kosten pro Mitglied berechnet werden.
Das die beiden `get_*`-Methoden statisch sind, macht keinen Sinn. Insgesamt machen diese simplen Getter und Setter in Python keinen Sinn. Weg damit.
Der Kommentar bei `add_member()` wäre besser der Inhalt des Docstrings. Der Methode fehlt das `self`-Argument und die sollte auf dem Objekt arbeiten und nicht auf der Klasse, weil da wie gesagt keine Variablen drauf gehören.
Namen für alles ausser Konstanten (hatten wir ja schon) und Klassen (MixedCase) wird in Python klein_mit_unterstrichen geschrieben. Also `member_type` statt `memberType`.
Beim vergleichen mit einem Buchstaben ist der Code etwas einfacher und weniger fehleranfällig wenn Du die Eingabe in kleinbuchstaben umwandelst, dann brauchst Du nur noch mit einem kleinen literalen Buchstaben vergleichen.
Was soll denn das `member`-Argument von `ResearchGroup.add_member()` sein? Du verwendest das beim erstellen von `Professor` und `WiMi`, aber die erben von `Member` und das erwartet *zwei* Argumente: die `id` und den `namen`‽ Und die Werte könnte man auch vom Benutzer abfragen, wenn man da sowieso schon Benutzerinteraktion in der Methode hat. Wobei die Benutzerinteraktion da nicht hingehört.
Du möchtest in einem Wörterbuch die Bedeutung von „actual“ und „current“ nachschlagen und künftig „actual“ nicht mehr falsch verwenden.
Für einen Professor wird bei der Eingabe `cost` erfragt und dann nicht verwendet. Warum wird das dann da überhaupt abgefragt? Kann es sein das meine Vermutung zu `cost` auf der `ResearchGroup` richtig ist und `cost` auch ein Attribut von `Member`-Objekten ist und das *da* eigentlich der Defaultwert 0 als Konstante sein soll? Wobei WiMis in der Realität ja auch nicht für lau arbeiten. Das ist sehr komisch. Ich würde also sagen `cost` ist ein ganz normales Attribut bei `Member`-Objekten.
Wenn man denn unbedingt abstrakte Klassen haben möchte bei denen Benutzer die nicht implementieten Methoden auch tatsächlich in abgeleiteten Klassen implementieren muss damit sich Exemplare davon erstellen lassen, dann gibt es dafür Dekoratoren im `abc`-Modul.
Der Kommentar „vererbte Klasse“ macht keinen Sinn. Das sieht man doch direkt in der Zeile danach am Code. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das beschreibt der Code bereits, sondern *warum* er es so macht, sofern das nicht offensichtlich ist.
Der Sinn von `Professor._cost_center_no` erschliesst sich mir so gar nicht. Ich hätte nicht einmal den Hauch einer Idee was das mal werden sollte…
`Presentation.change_date()` macht 0 Sinn. Also erst einmal würde man bei dem Namen erwarten, dass das Datum vom `Presentation`-Exemplar tatsächlich geändert wird. Und dann fehlt da ein Argument *auf was* es geändert wird. Dann wäre es aber ein Setter, die man in Python so nicht schreibt. Also soll das Datum vielleicht auf das aktuelle geändert werden. Dann ist `update_date()` ein besserer Name für die Methode.
Als Zwischenergebnis und nur sehr oberflächlich getestet:
Code: Alles auswählen
#!/usr/bin/env python3
import abc
import datetime
class ResearchGroup:
COST = 0
TOTAL_PRESENTATION = 40
def __init__(self, name, head):
self.name = name
self.head = head
self.members = list()
@property
def cost(self):
return sum(member.cost for member in self.members) + self.head.cost
def add_member(self):
"""Füge Professor oder Wimi als Mitglied hinzu."""
#
# TODO User interaction doesn't belong here!
#
member_type2create_func = {'p': Professor, 'w': WiMi}
member_type = input(
'Professor or WiMi member?: Type p for professor or w for Wimi'
'and press Enter '
).lower()
create_member = member_type2create_func[member_type]
id_ = int(input('Please enter id: '))
name = input('Please enter the name: ')
cost = int(input('Please enter the cost: '))
self.members.append(create_member(id_, name, cost))
def show(self):
print('Research group', repr(self.name), 'lead by:')
self.head.show()
print('Members:')
for member in self.members:
member.show()
print('Total cost:', self.cost)
class Member(abc.ABC):
def __init__(self, id_, name, cost):
self.id = id_
self.name = name
self.cost = cost
@abc.abstractmethod
def show(self):
pass
class Professor(Member):
def show(self):
print('Show Professor member:', self.name, ' Cost: ', self.cost)
class WiMi(Member):
def show(self):
print('Show WiMi member:', self.name, ' Cost:', self.cost)
class Presentation:
def __init__(self, title, date):
self.title = title
self.date = date
def update_date(self):
self.date = datetime.datetime.now()
def main():
research_group = ResearchGroup(
'Würgeschlangen', Professor(42, 'Evil', 23000)
)
research_group.add_member()
research_group.show()
if __name__ == '__main__':
main()