Storseminarium 4 - Experimentering
Innan seminariet ska du ha gått igenom Inför seminariet nedan och gjort tillhörande quiz. Syftet med detta är att du ska bekanta dig med innehållet så eventuella frågor kan redas ut under seminariet.
Denna sida visar en del av det som kommer att diskuteras på seminariet. Det kan hända att handledarna också tar upp andra uppgifter som inte behöver något specifikt studiematerial och då syns dessa uppgifter inte på sidan.
Inför seminariet
Övning 1: Definiera klass, skapa instans
Skriv in nedanstående klassdefinition för klassen Contact i en fil. Lägg sedan till kod som skapar två instanser av klassen. Referera till instanserna med separata variabler, c1 och c2.
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
c1 = Contact("Alice")
c2 = Contact("Bob")
Övning 2: Instansvariabler
Lägg till rader i din kod som sätter värdet på attributet phone_num i c1 till "0701-111111" och phone_num i c2 till "0702-222222". Skriv sedan ut värdet på alla instansvariabler i c1 och sedan alla värden på alla instansvariabler i c2.
Du behöver inte skriva någon metod för att tilldela eller skriva ut attributen, utan du kan referera till dem direkt med punktnotation via objektet, t.ex. c1.name eller c2.phone_num. Varför är det tillåtet i det här fallet?
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
c1 = Contact("Alice")
c2 = Contact("Bob")
c1.phone_num = "0701-111111"
c2.phone_num = "0702-222222"
print(c1.name, c1.phone_num)
print(c2.name, c2.phone_num)
Det är tillåtet att direkt manipulera attributen utanför klassen eftersom de inte inleds med ett understreck (_) och alltså kan betraktas som “publika”.
Övning 3: Metoder
Lägg till en metod till klassen Contact med namnet append_to_name(string_to_append) som lägger till strängen string_to_append till instansvariabeln name i den egna instansen. Lägg sedan till kod i filen som
- Efter att instanserna
c1respektivec2skapats ska strängen" Efternamnsson"läggas till båda instansernas attributname. Använd metodenappend_to_name(string_to_append). - Skriver ut värdena på instansvariabeln
namefrån bådec1ochc2(efter att suffixet lagts till).
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
def append_to_name(self, string_to_append):
self.name += string_to_append
c1 = Contact("Alice")
c2 = Contact("Bob")
c1.append_to_name(" Efternamnsson")
c2.append_to_name(" Efternamnsson")
print(c1.name)
print(c2.name)
Övning 4: Instanser i en lista
Lägg till kod som skapar en lista som refereras till med variabeln contact_list samt lägger in tre instanser av klassen Contact i den listan (hitta själv på namn och telefonnummer). Skriv sedan en loop som skriver ut (med print()) varje element i listan contact_list.
Utskrifterna av Contact-instanserna bör se ut som något i stil med <__main__.Contact object at 0x10b9a31d0>.
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
def append_to_name(self, string_to_append):
self.name += string_to_append
c1 = Contact("Alice")
c2 = Contact("Bob")
c3 = Contact("Charlie")
c1.phone_num = "0701-111111"
c2.phone_num = "0702-222222"
c3.phone_num = "0703-333333"
contact_list = [
c1,
c2,
c3
]
for contact in contact_list:
print(contact)
Övning 5: Metoden __str__
Lägg till metoden __str__ enligt nedan till klassen Contact och kör sedan den existerande koden igen. Nu bör namn och telefonnummer skrivas ut istället. Varför?
def __str__(self):
return f"Contact(Name: {self.name}, Phone: {self.phone_num})"
class Contact:
def __init__(self, name):
self.name = name
self.phone_num = ""
def append_to_name(self, string_to_append):
self.name += string_to_append
def __str__(self):
return f"Contact(Name: {self.name}, Phone: {self.phone_num})"
c1 = Contact("Alice")
c2 = Contact("Bob")
c3 = Contact("Charlie")
c1.phone_num = "0701-111111"
c2.phone_num = "0702-222222"
c3.phone_num = "0703-333333"
contact_list = [
c1,
c2,
c3
]
for contact in contact_list:
print(contact)
Detta fungerar eftersom Python automatiskt anropar metoden __str__ när ett objekt ska konverteras till en sträng, till exempel vid utskrift med print(). Genom att definiera __str__ i klassen Contact specificerar vi hur objekt av denna klass ska representeras som strängar.
Övning 6: Från klassdiagram till kod
Implementera klassen Vector enligt klassdiagrammet nedan. Metoden __str__ ska returnera en strängrepresentation av vektorn i formatet Vector(components: (x1, x2, x3, ...)).
Vad representerar de olika metoderna? Vad innebär det att _components inleds med ett understreck?
Skapa en vektorinstans v1 med komponenterna 1, 2 och 3. Anropa sedan metoden dimension() på den instansen och skriv ut resultatet.
class Vector:
def __init__(self, components):
self._components = components
def dimension(self):
return len(self._components)
def get(self):
return self._components
def __str__(self):
return f"Vector(components: {self._components})"
v1 = Vector((1, 2, 3))
print(v1.dimension())
Övning 7: Skapa instanser från en klassdefinition
Ibland är det meningsfullt att skapa nya instanser av en klass inuti en metod i samma klass. Utöka klassen Vector enligt klassdiagrammet nedan:
Testa att multiplicera vektorn v1 med skalären 3 genom att anropa metoden scale på v1 och skicka in värdet 3 som argument. Skriv sedan ut den nya vektorn.
class Vector:
def __init__(self, components):
self._components = components
def dimension(self):
return len(self._components)
def get(self):
return self._components
def __str__(self):
return f"Vector(components: {self._components})"
def scale(self, factor):
acc = []
for x in self._components:
acc.append(x * factor)
return Vector(tuple(acc))
v1 = Vector((1, 2, 3))
v2 = v1.scale(3)
print(v2)
Övning 8: Använda flera instanser av en klass i klassdefinitionen
Ibland behöver vi hantera mer än en instans av klassen i en metod i samma klass. Ett relevant exempel för vektorer skulle vara t.ex. när vi vill beräkna vektoraddition. Utöka klassen Vector enligt klassdiagrammet nedan:
Hur kommer vi åt komponenterna i den andra vektorn inuti add? Kan vi använda instansvariabeln _components direkt eller ska vi använda någon metod för att hämta komponenterna?
Hur skulle du kunna använda metoderna add? Testa att skapa en ny vektor v2 med komponenterna 4, 5 och 6. Använd sedan metoden add på v1 för att beräkna summan av v1 och v2. Skriv ut resultatet. Skriv också ut v1 och v2 för att verifiera att de inte har ändrats.
class Vector:
def __init__(self, components):
self._components = components
def dimension(self):
return len(self._components)
def get(self):
return self._components
def __str__(self):
return f"Vector(components: {self._components})"
def scale(self, factor):
acc = []
for x in self._components:
acc.append(x * factor)
return Vector(tuple(acc))
def add(self, other):
if self.dimension() != other.dimension():
raise ValueError("Vectors must have the same dimension")
acc = []
for i in range(self.dimension()):
acc.append(self._components[i] + other._components[i])
return Vector(tuple(acc))
v1 = Vector((1, 2, 3))
v2 = Vector((4, 5, 6))
v3 = v1.add(v2)
print(v3)
print(v1)
print(v2)
I Python är det tillåtet att direkt referera till attributen i en annan instans av samma klass, även om de inleds med ett understreck (_). I detta fall använder vi _components direkt eftersom vi är inom metoden add i klassen Vector. Detta är dock ett undantag från den allmänna regeln att attribut som inleds med understreck bör betraktas som “privata” och inte refereras annat än genom self.
Sidansvarig: Johan Falkenjack
Senast uppdaterad: 2025-10-17
