TDDE44 Programmering grundkurs
Föreläsning 5.1
Jody Foo, jody.foo@liu.se
Sammanfattning av period 1
⁃ Grundläggande datatyper/datastrukturer
⁃ Syntax och användning av funktioner
⁃ Syntax och användning av kontrollstrukturer (villkor, loopar)
⁃ Repetition på två sätt: iteration och rekursion
⁃ Dela upp problem, bryta ut funktioner, introduktion till abstraktion
Föreläsningsöversikt, FÖ 5.1-5.2
⁃ Objektorienterad programmering (OOP)
Begrepp: klass, instans (objekt), instansvariabler, metoder Syntax: skapa klasser, använda instanser
Funktioner som objekt
Exempel på OOP: grafiska gränssnitt UML-diagram
⁃ Kodstandarder för Python: PEP8 & PEP257
⁃ Programmeringsmetod
Implementation, testning, felsökning
5.1.1 Vad är objektorienterad
programmering?
Programmeringsparadigm
⁃ Funktionell programmering
⁃ Procedurell programmering
⁃ Logikprogrammering
⁃ Objektorienterad programmering
Funktionell programmering:
Abstrakta datatyper (ADT)
⁃ Liten uppsättning primitiva datatyper i
programmeringsspråk, t.ex. heltal, flyttal, strängar, listor
⁃ Hur gör vi för att representera begrepp/koncept som inte kan kokas ner till någon av dessa datatyper och de
operationer vi kan utföra på dem?
⁃ T.ex. en person, en kundkorg i ett e-handelssystem etc
Funktionell programmering:
Abstrakta datatyper (ADT)
⁃ Barbara Liskov, 1974
⁃ Användning av abstrakta datatyper var Liskovs banbrytande angreppssätt för att hantera detta.
⁃ En abstrakt datatyp defineras av en uppsättning operationer som kan utföras på den.
⁃ I ett funktionellt programmeringsparadigm definierar vi ett antal funktioner som opererar på variabler som motsvarar denna abstrakta datatyp
Funktionell programmering:
Abstrakta datatyper (ADT)
⁃ Exempel: Person i ett matchingsprogram
⁃ I vår abstraktion (modell) så jobbar personer som har en gemensam favoritfärg bra ihop
⁃ Vi behöver följande operationer:
⁃ Skapa en person p som har namnet n
create_person(n) → p
⁃ Lägg till favoritfärg c till person p
add_fav_colour(p, c) → p
⁃ Ta reda på om en person p1 och en person p2 matchar
matches(p1, p2) → {True, False}
Funktionell programmering:
Abstrakta datatyper (ADT)
⁃ Den abstrakta datatypen kan implementeras på många olika sätt.
⁃ I Python, t.ex. antingen som nästlad lista eller ett dictionary.
⁃ Det viktiga från Liskovs arbete är själva idén om vi kan skapa egna abstraktioner och jobba med dem i ett program.
⁃ Med ett renodlat funktionellt programmeringsspråk finns dock inga språk-konstruktioner som specifikt stödjer detta abstraktionsarbete.
⁃ T.ex. det finns inget som hindrar oss att använda funktionen
add_fav_colour() på två heltal.
Objektorienterad programmering
⁃ Ett alternativ till att använda funktioner för att strukturera kod: Objekt istället för abstrakt datatyp
⁃ Bättre sätt att organisera större projekt - återanvändning
⁃ C++, Objective-C, C# och Java är exempel på andra OO programmeringsspråk
Objektorienterad programmering (OOP)
⁃ Objekt är i fokus jämfört med funktioner i fokus som vid funktionell programmering.
⁃ Man försöker relatera data och metoder till objekt.
⁃ Inkapsling: Både data och metoder kan "ägas"/tillhöra objekt (eng. encapsulation)
⁃ Objekt har egenskaper (data) och beteenden (funktionalitet)
Objektorienterad programmering (OOP)
⁃ En klass är en mall, en beskrivning (definition) av något som kan finnas när ett program körs.
⁃ Det som finns i världen är instanser av klasser, även kallade för objekt.
⁃ En klassdefinitioner används för att skapa ett objekt (instans av en klass)
⁃ En klass beskriver vilka egenskaper (instansvariabler) dess instanser har och vilka beteenden (metoder) den har.
Bygga med objekt. UML-diagram,
exempel 1
Bygga med objekt. UML-diagram,
exempel 2
Objektorienterad programmering
använda objekt med punktnotation
Ni har redan använt objekt...
# en lista är ett objekt lista1 = []
# Ett objekt har metoder som man meddelar att man vill köra genom
# att använda punktnotation. Vad händer egentligen nedan?
lista1.append("en sträng")
Ni har redan använt objekt...
# en sträng är ett objekt
a_string = "visst är python roligt!"
# Ett objekt har metoder som man meddelar att man vill köra genom
# att använda punktnotation. Vad händer egentligen nedan?
print(a_string.upper())
5.1.2 Definiera en klass och
skapa objekt
Klassen definierar en klass av objekt
⁃ Från Liskov (1974): "an abstract data type defines a class of abstract objects which is completely characterized by the
operations available on those objects"
⁃ När vi definerar en klass i objektorienterad programmering, definierar vi
egenskaper: data som tillhör objekt av denna klass
beteenden: operationer vi kan utföra på objekt av denna klass
Objekt, dess egenskaper och beteenden
klassens namn
variabler
metoder
Definition av en klass
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
Skapa/instansiera ett objekt av en viss klass
⁃ För användardefinierade klasser använder vi klassens namn följt ett parentespar med eventuella argument.
⁃ Om vi t.ex. har definierat klassen Book kan vi skapa en instans av den klassen med book = Book()
⁃ Inbyggda klasser, t.ex. listor och dictionaries har syntaktiskt socker för att skapa nya instanser av dem {}, []
OOP: Arv - ett sätt att
återanvända kod
Arv
⁃ Ytterligare ett viktigt koncept för OOP är arv
⁃ Arv låter oss skapa härledda klasser (även kallade för subklasser).
⁃ En härledd klass har alla egenskaper och beteenden som sin basklass, men kan utöka dessa.
⁃ Analogt exempel från biologin: taxonomi över flora och fauna
Definiera en klass
⁃ Python för bok över vilka klasser som finns. Varje klass lagras i en hierarki av klasser.
⁃ Klasshierarkin finns för att vi ska kunna återanvända kod från "klassföräldrar", basklasser (kallas ibland även för
superklasser).
⁃ För att definiera en klass använder vi nyckelordet class följt av ett namn, samt ett parentespar med den nya klassens
basklass. Tills vidare låter vi denna vara klassen object.
⁃ Definition av ny klass, Book.
class Book(object):
pass
Skapa/instansiera ett objekt av en viss klass
⁃ För användardefinierade klasser använder vi klassens namn följt ett parentespar med eventuella argument.
⁃ Om vi t.ex. har definierat klassen Book kan vi skapa en instans av den klassen med book = Book()
⁃ Inbyggda klasser, t.ex. listor och dictionaries har syntaktiskt socker för att skapa nya instanser av dem {}, []
Struktur hos klassdefinitioner
Klassen Book
Book title
author year
__init__()
print_citation()
Definition av en klass
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
Definition av en klass
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
Nyckelordet class berättar att vi definierar en klass.
class Book(object):
betyder alltså "vi ska nu definiera klassen Book som har object som basklass"
Klassnamn bör vara substantiv och ska enligt standard börja med stor bokstav.
Efter klassnamnet kommer namnet på klassens basklass
Definition av en klass
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
Nyckelordet "def" används för att definiera metoder i en klass.
Variabler som hör till en instans har "self."
som prefix.
Alla metoder tar in en referens till den
instans som de tillhör som första argument.
Python skickar detta automatiskt.
Definition av en klass
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
Metoden __init__ är speciell. Den
beskriver det som händer när en instans av klassen skapas.
Instansvariabler, variabler som tillhör en instans av en klass används med referensen self.
self är en referens till den instans metoden anropas ifrån. Python skickar med den
automatiskt när ett anrop på formen objekt.metod() görs.
Skapa och använda objekt
⁃ Skapa objekt (instanser av en klass)
ClassName() → objekt (instans av klassen ClassName)
bok1 = Book("Python från början")
⁃ Använda instansvariabler
instans.namn_på_instansvariabel
bok1.title
bok1.title = "Python från början!"
⁃ Använda metod
instans.namn_på_metod()
bok1.print_citation()
Skapa och använda objekt
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def print_citation(self):
citation = "{}. ({}). {}."
print(citation.format(self.author, self.year, self.title))
# skapa instans
bok1 = Book("Python från början")
# ändra på instansvariabel
bok1.author = "Jan Skansholm"
# använda metod
bok1.print_citation()
5.1.3 Den speciella metoden
__str__
Speciella metoder, börjar och slutar med __
⁃ Det finns en uppsättning metoder som vi kan definiera i en klass som Python vet om och använder i specifika
situationer.
⁃ Exempel
Metoden __init__ används när en instans av en klass skapas Metoden __str__ används när en instans av en klass (ett
objekt) ska visas som en sträng
⁃ OBS! Dessa metoder bör inte anropas av er explicit, utan Python använder dem i speciella situationer.
Instansvariabler och metodanrop
class Book(object):
def __init__(self, title):
self.title = title
self.author = "Unknown"
self.year = "N/A"
def __str__(self):
citation = "{}. ({}). {}."
return citation.format(self.author, self.year, self.title)
bok1 = Book("The Practice of Computing using Python") bok2 = Book("PSwAaDSuP")
# OBS! Vi anropar inte själva på __str__ utan det är
# print-funktionen som använder den automatiskt print(bok1)
print(bok2)
5.1.4 Funktionsobjekt
Funktionsobjekt
Alla värden (data) är objekt i Python.
Definierade funktioner kan också ses som en
typ av värden - funktionsobjekt
Funktionsobjekt
⁃ Klasser kan instansieras och producera objekt
⁃ I Python är även funktioner objekt.
⁃ En funktion:
def hejsan():
print("Hejsan")
⁃ Ett funktionanrop: hejsan()
⁃ Funktionsobjektet: hejsan
Exempel på funktionsobjekt
def print_hello():
print("Hello World!") bacon = print_hello
bacon()
# utskrift
# Hello World!
Användning av funktionsobjekt
⁃ Skicka funktioner som argument till andra funktioner för att ändra deras beteenden.
⁃ Exempel
En funktion som sorterar data som också tar emot en funktion som argument. Beroende på den funktionen som skickas in
(som bestämmer vad som ska jämföras) kan
sorteringsfunktionen sortera utifrån olika egenskaper.
En funktion som läser in data, load_data(), som också tar emot en funktion som argument. Beroende på vilken funktion man skickar med kan olika filformat läsas in.
5.1.5 OOP och grafiska
gränssnitt
Grafiska gränssnitt
exempel på tillämpning av objektorienterad
programmering
Programflöde: GUI
⁃ GUI = Graphical User Interface
⁃ Icke-linjär interaktion, händelsestyrt
⁃ Reaktivt gränssnitt - tät återkoppling
⁃ Interaktion via mus och tangentbord
⁃ Interaktion med en begränsad och standardiserad uppsättning widgets (oftast)
Om modulen tkinter
⁃ Standardramverk för grafiska gränsnitt för Python
import tkinter
⁃ Olika widgetklasser finns: faktiska gränssnittskomponenter är instanser av klasserna
⁃ Olika inställningar kan ges när man skapar en widget.
Widgets
http://pythonwiki.tiddlyspot.com/#%5B%5BVisual%20Guide%20to%20Tkinter%20widgets%5D%5D
Litet exempel
import tkinter as tk import random
def clicked():
colors = [("red", "white"), ("green", "black"), ("blue", "white")]
bg_color, fg_color = random.choice(colors)
label.config(bg=bg_color, fg=fg_color, text="button clicked")
def mouse_enter(event):
label.config(text="mouse over")
def mouse_leave(event):
label.config(text="mouse exit")
# skapa ett Tk-fönster root = tk.Tk()
# skapa label-widget
label = tk.Label(root, text="Hello!") label.pack(fill=tk.X)
# koppla ihop händelser med funktioner. OBS! Funktionsobjekt som argument.
label.bind("<Enter>", mouse_enter) label.bind("<Leave>", mouse_leave)
# skapa knappen. OBS! Funktionsobjekt som argument
button = tk.Button(root, text="Press Me!", command=clicked) button.pack(fill=tk.X)
# starta GUI-loopen root.mainloop()