====== OOP Einführung ======
===== - Klassen und Objekte =====
Studiere die {{ :talit:2022_talit_oop_python_i.pdf|Slides}} für eine detaillierte Einführung in die **objektorientierte Programmierung (OOP)**. Hier im Wiki sind einfach die allerwichtigsten Grundlagen angegeben.
In der objektorientierten Programmierung schreibt man **Klassen**, von welcher man dann **Objekte** instanziiert.
Wikipedia sagt dazu:
"Unter einer Klasse (auch Objekttyp genannt) versteht man in der objektorientierten Programmierung ein abstraktes Modell bzw. einen Bauplan für eine Reihe von ähnlichen Objekten.
Die Klasse dient als **Bauplan** für die Abbildung von realen Objekten in Softwareobjekte und beschreibt **Attribute (Eigenschaften)** und **Methoden (Verhaltensweisen)** der Objekte. Verallgemeinernd könnte man auch sagen, dass eine Klasse dem Datentyp eines Objekts entspricht."
Ein **Beispiel** für eine Klasse, mit der man Personen z.B. für eine Personalverwaltungssoftware in einer Schule, darstellen kann, ist hier angegeben:
class Person:
def __init__(self,_name,_address,_birthday,_type,_position,_klasse):
self.name = _name
self.address = _address
self.birthday = _birthday
self.type = _type
self.position = _position
self.klasse = _klasse # can't use 'class' bc is keyword
def get_info(self):
# TODO: return different string for teachers and students
return f"Name: {self.name}, Adresse: {self.address}, Geburtstag: {self.birthday}, Typ: {self.type}"
def get_age(self):
# TODO: determine and return age using datetime module (compare date today with birthdate)
raise NotImplementedError()
def change_klasse(self,x=1):
# TODO: change class by x, default value is x=1, example: for x=-1 from 3Mfz -> 2Mfz
raise NotImplementedError()
Beachte dabei das Keyword **self.** Dieses repräsentiert das jeweilige Objekt. Beachte auch, dass es Klassenmethoden als erstes Argument übergeben werden muss.
Nun können wir **Objekte** der Klasse **instanziieren**:
# instantiate single object:
scb = Person("Bert Schreiner", "Hoehenweg 8, 8590 Romanshorn TG", "07.12.1969", "LP","HL",None)
# print an attribute
print(scb.name)
# change an attribute
scb.address = "Kirchgasse 7, 8594 Kesswil" # change address of scb
# instantiate objects as elements of a list directly
persons = [
Person("Bert Schreiner", "Hoehenweg 8, 8590 Romanshorn TG", "07.12.1969", "LP","HL",None),
Person("Monika Hohler", "Seeblickstrasse 17, 9306 Freidorf", "24.05.1990", "LP","LB1",None),
Person("Verena Keller", "Saentisstrasse 22, 8580 Amriswil", "03.02.2007", "STU",None,"1Fd"),
Person("Heiri Meier", "Kreisstrasse 3, 9322 Egnach", "11.09.2005", "STU",None,"3Mfz")
]
# go through list of objects and print
for person in persons:
print(person.name)
Halte dich an folgende **Style-Konventionen:**
* Attribute: snake_case
* Klassennamen im UpperCamelCase
{{ :talit:inthatcase.jpg?400 |}}
==== Auftrag 1: Klasse Person ====
1. Implementiere selbst die **Klasse Person**. Kein Copy-Paste, so viel wie geht aus Erinnerung anstelle Abschreiben
1. Instanziiere selbst mind. vier **Objekte** der Klasse von echten Personen (du selbst, Kolleg:innen, Lehrpersonen, siehe ISY oder nachfragen)
1. Füge weitere **Attribute** hinzu: Telefonnummer & Mail-Adresse
1. Erweitere `get_info()`: Andere Info für LP und STU:
1. für LP: "Name: Bert Schreiner, Adresse: … , … , … , Typ: LP, Position: HL"
1. für STU: "Name: Verena Keller, Adresse: … , … , … , Typ: STU, Klasse: 1Fd"
1. Zeige auch neue Attribute darin an.
1. Implementiere Klassenmethode `increase_klasse()`. Gebe Fehlermeldung aus, falls für Lehrperson aufgerufen wird.
1. Implementiere Klassenmethode `get_age()`. Tipp: Verwende datetime- und dateutil-Module
++++Lösung|
from datetime import datetime
from dateutil import relativedelta
class Person:
def __init__(self,_name,_address,_birthday,_phone,_mail,_type,_position,_klasse):
self.name = _name
self.address = _address
self.birthday = _birthday
self.phone = _phone
self.mail = _mail
self.type = _type
self.position = _position
self.klasse = _klasse # can't use 'class' bc is keyword
def get_info(self):
str_all = f"Name: {self.name}, Adresse: {self.address}, Geburtstag: {self.birthday}, Phone: {self.phone}, Mail: {self.mail}, Typ: {self.type} "
if self.type == "LP":
return str_all + f"Position: {self.position}"
else:
return str_all + f"Klasse: {self.klasse}"
def get_age(self):
birthdate = datetime.strptime(self.birthday,"%d.%m.%Y")
now = datetime.now()
diff = relativedelta.relativedelta(now,birthdate)
return diff.years
def change_klasse(self,x=1):
yr = int(self.klasse[0]) + x
self.klasse = str(yr) + self.klasse[1::]
# instantiate objects, store in list
persons = [
Person("Bert Schreiner", "Hoehenweg 8, 8590 Romanshorn TG", "07.12.1969","071 847 41 23","scb@ksr.ch","LP","HL",None),
Person("Monika Hohler", "Seeblickstrasse 17, 9306 Freidorf", "24.05.1990","071 369 54 11", "hom@ksr.ch", "LP","LB1",None),
Person("Verena Keller", "Saentisstrasse 22, 8580 Amriswil", "03.02.2007","071 345 67 78", "verkelle@ksr.ch", "STU",None,"1Fd"),
Person("Heiri Meier", "Kreisstrasse 3, 9322 Egnach", "11.09.2005", "071 499 85 31","heiri@rasenmeier.ch", "STU",None,"3Mfz")
]
sca = Person("Andreas Schärer","Weinfelden","03.09.1987","123","sca@ksr.ch","LP","HL",None)
print(sca.get_age())
verkelle = Person("Verena Keller", "Saentisstrasse 22, 8580 Amriswil", "03.02.2007","071 345 67 78", "verkelle@ksr.ch", "STU",None,"1Fd")
heimeier = Person("Heiri Meier", "Kreisstrasse 3, 9322 Egnach", "11.09.2005", "071 499 85 31","heiri@rasenmeier.ch", "STU",None,"3Mfz")
verkelle.change_klasse() # Verena
heimeier.change_klasse(-1) # Heiri has to repeat a year
print(verkelle.klasse)
print(heimeier.klasse)
++++
==== Auftrag 2: OOP im Game ====
1. Überlege dir mit einer Kolleg:in und mache Notizen:
1. Wie könnte man OOP im Game von früher sinnvoll einsetzen?
1. Welche Klasse(n) & Objekte braucht es?
1. Welche Attribute und Methoden haben diese?
1. Bespreche mit der Lehrperson
1. Setze dies dann in der nächsten Aufgabe um.