Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py...

82
Föreläsning 3 och 4 Dagens ämnen: Funktioner Moduler Klasser Arv Operatorer Felhantering Filhantering (serialisering, pickle) Code Kata 5

Transcript of Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py...

Page 1: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Föreläsning 3 och 4

Dagens ämnen: Funktioner Moduler Klasser Arv Operatorer Felhantering Filhantering (serialisering, pickle) Code Kata 5

Page 2: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Vad är en funktion?

•I matematisk mening är en funktion en “låda” som givet indata producerar utdata.

•Ett exempel är kvadreringsfunktionen:

IndataFunktion

Utdata

4 Indata*Indata 16

Page 3: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Funktion inom programmering

En funktion kan fungera helt analogt med den matematiska definitionen, men kan skilja sig på flera punkter. Inom programmeringen kan en funktion:

•Returnera olika värden för samma indata (beroende på externa data såsom tidpunkt, globala parametrar eller slumpen).

•Ha sidoeffekter.

Page 4: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Varför använda funktioner?

• Större program måste delas upp i hanterliga delar.

• Gör det lättare att återanvända kod, både inom ett program och i flera program.

• Gömma detaljer i en implementation.

• Oberoende programdelar.

• Lagerdesign.

Page 5: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Inbyggda funktioner

• Python har ett antal funktioner som alltid finns tillgängliga.

• Funktioner anropas funktionsnamn(arg_1, arg_2,...)>>> abs(-7)7>>> max(3.5,6.2)6.2000000000000002

Page 6: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Funktioner och metoder

Vi skiljer på funktioner och metoder:

• En funktion är ett fristående kodavsnitt som inte är associerat till ett objekt eller en klass.

• En metod anropas “för” ett objekt eller en klass.

• Ett objekts metoder kallas instansmetoder.

• En klass metoder kallas klassmetoder.

>>> s = "Testtext">>> id(s) # Funktion14858240>>> hash(s) # Funktion728880665>>> s.upper() # Metod'TESTTEXT'>>> s.split("t") # Metod['Tes', '', 'ex', '']

Page 7: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Skriva egna funktioner

• En funktion skapas med det reserverade ordet def följt av funktionens namn och ett kolon.

• Funktionnamn följer samma regler som variabelnamn. # function_01.py

def function_a():print "Detta skrivs inuti funktionen."

print "Detta skrivs först."function_a() # Funktionen anropasprint "Detta skrivs efter metodanropet."

$> python function_01.pyDetta skrivs först.Detta skrivs inuti funktionen.Detta skrivs efter metodanropet.

Page 8: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Argument till funktioner

• Vi kommunicerar med funktioner genom att skicka argument i funktionsanropet.

# function_02.py

def greeting(name, age):print """Hej %s. Du är %i år gammal.""" % (name, age)

greeting("Maja", 23)greeting("Pelle", 31)

$> python function_02.pyHej Maja. Du är23 år gammal.Hej Pelle. Du är31 år gammal.

Page 9: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Standardvärden för argument

• Om vi inte alltid vill ange alla argument kan vi ange standardvärden.

# function_03.py

def greeting(name, age=20):print """Hej %s. Du är %i år gammal.""" % (name, age)

greeting("Maja", 23)greeting("Pelle")

$> python function_03.pyHej Maja. Du är23 år gammal.Hej Pelle. Du är20 år gammal.

Page 10: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Standardvärden måste anges i rätt ordning

• Problem med många argument: Argument fylls på i den ordning de anges i funktionshuvudet.# function_04.py

def greeting(name="Okänd", age=20):print """Hej %s. Du är %i år gammal.""" % (name, age)

greeting()greeting("Pelle")greeting(45) # Fel resultat

$> python function_04.pyHej Okänd. Du är 20 år gammal.Hej Pelle. Du är 20 år gammal.Hej 45. Du är 20 år gammal.

Page 11: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Lösning: Namngivna argument

• Vi kan lösa detta genom att ange vilka variabler som anges i funktionsanropet.# function_05.py

def greeting(name="Okänd", age=20):print """Hej %s. Du är %i år gammal.""" % (name, age)

greeting()greeting("Pelle") # Fungerar fortfarandegreeting(name="Pelle") # Ekvivalentgreeting(age=45) # Ger rätt resultatgreeting("Maja", 33)greeting(name = "Maja", age = 33) # Ekvivalent

$> python function_05.pyHej Okänd. Du är 20 år gammal.Hej Pelle. Du är 20 år gammal.Hej Pelle. Du är 20 år gammal.Hej Okänd. Du är 45 år gammal.Hej Maja. Du är 33 år gammal.Hej Maja. Du är 33 år gammal.

Page 12: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Funktionsargument och referenser

Slutsats: Tal hanteras som värdeanrop. (Inkonsekvent m.a.o.)

# function_06.pydef process_people(mean_age, people):

print "Utför funktionen"mean_age = 0for person in people:

person["name"] = person["name"].upper()mean_age += person["age"]person["age"] = 0

mean_age /= float(len(people))print "Medelålder i funktionen: %.2f" %mean_age

list_of_people = [{"name" : "Maja", "age" : 45},{"name" : "Kalle", "age" : 22},{"name" : "Klara", "age" : 53},{"name" : "Pelle", "age" : 68}]a = 30print "a:s värde innan funktionen: %.2f" % aprint "people innan funktionen:"print list_of_peopleprocess_people(a, list_of_people)print "a:s värde efter funktionen: %.2f" % aprint "people efter funktionen:"print list_of_people

$> python function_06.pya:s värde innan funktionen: 30.00people innan funktionen:[{'age': 45, 'name': 'Maja'},{'age': 22, 'name': 'Kalle'},{'age': 53, 'name': 'Klara'},{'age': 68, 'name': 'Pelle'}]Utför funktionenMedelålder i funktionen: 47.00a:s värde efter funktionen: 30.00people efter funktionen:[{'age': 0, 'name': 'MAJA'},{'age': 0, 'name': 'KALLE'},{'age': 0, 'name': 'KLARA'},{'age': 0, 'name': 'PELLE'}]

Page 13: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Returvärden

• För att returnera ett värde från en funktion används return-satsen.# return_values_01.py

def my_own_join(texts, separator=" "):s = ""for text in texts:

s += text + separators = s[:-len(separator)] + "."

return s

my_text_pieces = ["Detta", "är", "inte","så", "meningsfullt"]print my_own_join(my_text_pieces, "_")

$> python return_values_01.pyDetta_är_inte_så_meningsfullt.

Page 14: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Alla funktioner returnerar något

• En tom return-sats eller ingen return-sats alls returnerar None.# return_values_02.pydef positive(value):

if value <= 0:return

else:return "Värdet är positivt."

print "Detta skrivs aldrig ut."

print positive(40)print positive(-10)a = positive(-10)print a.__class__

$> python return_values_02.pyVärdet är positivt.None<type 'NoneType'>

Page 15: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Flera returvärden

• Om flera returvärden anges tilldelas de i tur och ordning de variabler som anges vid funktionsanropet.

• Om flera returvärden tas emot av en ensam variabel returneras värdena som en tuplett.

# return_values_03.pydef min_max(seq):

return min(seq), max(seq)

a = [3, 573, 234, 24]minimum, maximum = min_max(a)print minimum, maximumresult = min_max(a)print resultprint result.__class__

$> python return_values_03.py3 573(3, 573)<type 'tuple'>

Page 16: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Returvärden eller “in-place”

• Eftersom argumenten är referenser kan data manipuleras utan att returnera värden.

• Värdeanrop kan designmässigt vara ett vettigare val eftersom det minskar kopplingarna mellan programenheter.

• Referensanrop ger dock enklare och snabbare kod än värdeanrop, särskilt då stora datamängder hanteras.

Page 17: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Funktioner och subrutiner

• Ibland kallas funktioner som inte returnerar ett värde för subrutiner.

• Denna praxis finns inte inom Python.

• En funktion är en funktion oavsett antal returvärden.

Page 18: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Moduler

• Då man skriver större program är det mycket opraktiskt att spara all kod i en och samma fil.

• För att underlätta underhåll och återanvändning delas programmen upp i mindre enheter, moduler.

• Moduler används även för att organisera variabler i namnrum, mer om detta senare.

Page 19: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Standardmoduler

• Python har ett antal moduler som alltid är tillgängliga för import.

• Moduler importeras med import-satsen.>>> sysTraceback (most recent call last):File "<stdin>", line 1, in <module>NameError: name 'sys' is not defined>>> import sys>>> sys<module 'sys' (built-in)>>>> sys.version'2.4.3 (#1, Dec 11 2006, 11:39:03) \n[GCC 4.1.1 20061130 (Red Hat 4.1.1-43)]'

Page 20: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Skriva egna moduler

• Betrakta min_max-funktionen ovan. Den är tillräckligt allmän för att lägga i en modul med diverse nyttiga funktioner.

# util_functions.py

def min_max(seq):return min(seq),

max(seq)# module_prog_01.py

import util_functionsa = [3, 573, 234, 24]print "Min = %i, max = %i" \

% util_functions.min_max(a)

$> python module_prog_01.pyMin = 3, max = 573

• Modulen importeras med import filnamn.

• Observera hur inbäddningen av returvärdena sker i utskriften.

Page 21: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Testkod i moduler

• De flesta moduler definierar klasser och funktioner som ska användas i ett större program.

• Trots detta kan det vara lämpligt att inkludera testkod direkt i modulerna.

• Denna kod fungerar dels som testkod men även som en inbyggd instruktion till hur modulen används.

Page 22: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel på testkod i modul

# util_functions.py# Version 2 med testkod

def min_max(seq):return min(seq), max(seq)

if __name__ == "__main__":# Utför modultesta = [3, 573, 234, 24]print "Min = %i, max = %i" \

% min_max(a)

$> python util_functions.pyMin = 3, max = 573$> pythonPython 2.4.3 (#1, Dec 11 2006, 11:39:03) [GCC 4.1.1 20061130 (Red Hat 4.1.1-43)] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> import util_functions>>> util_functions.min_max([4, 6, 2])(2, 6)

Page 23: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Sökvägar till moduler

• I exemplet ovan ligger filen med modulen i samma mapp som programmet som inkluderar den.

• Pythontolken letar alltid i den aktuella mappen först.

• Därefter söks i mapparna som definieras i sys.path.

• Nya sökvägar kan läggas till under exekveringen med sys.path.append(“sökväg”) som för en vanlig lista.

• Permanenta sökvägar kan läggas till i systemvariabeln PYTHONPATH.

>>> import sys>>> sys.path['', 'd:\\program\\python25', 'C:\\WINDOWS\\system32\\python25.zip','d:\\program\\python25\\DLLs', 'd:\\program\\python25\\lib','d:\\program\\python25\\lib\\plat-win', 'd:\\program\\python25\\lib\\libtk','d:\\program\\python25\\lib\\site-packages']

Page 24: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Namnrum

• Alla variablers namn ordnas i namnrum.

• Varje namn kan endast referera till ett objekt åt gången i varje namnrum.

• Däremot kan samma namn finnas i godtyckligt många namnrum utan att störa varandra.

• På rotnivån finns ett globalt namnrum som alltid finns tillgängligt.

• En variabels räckvidd (scope), definieras som den programkod som har tillgång till det namnrum där variabeln finns definierad.

Page 25: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Scope och variablers räckvidd

• Samma variabelnamn kan finnas i flera namnrum samtidigt och referera till olika objekt.# namespaces_01.py

def function_1():s = "lokal text"print "Lokalt i function_1: s =", s

s = "global text"print "Globalt: s =", sfunction_1()print "Globalt: s =", s

$> python namespaces_01.pyGlobalt: s = global textLokalt i function_1: s = lokal textGlobalt: s = global text

Page 26: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Globala namnrummet

• Om ingen lokal variabel med det efterfrågade namnet existerar letar tolken vidare i globala namnrummet.

# namespaces_02.py

def function_1():# Ingen tilldelningprint "Lokalt i function_1: s =", s

s = "global text"print "Globalt: s =", sfunction_1()print "Globalt: s =", s

$> python namespaces_02.pyGlobalt: s = global textLokalt i function_1: s = global textGlobalt: s = global text

Page 27: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Tolken söker inte hierarkiskt

• Tolken letar antingen i det aktuella lokala namnrummet samt i det globala.

• Eventuella andra lokala namnrum genomsöks inte.

# namespaces_03.pydef function_1():

a1 = 10function_2()

def function_2():a2 = 20function_3()

def function_3():a3 = 30print "a =", a # Globala namnrummetprint "a1 =", a1 # Utlöser NameError"print "a2 =", a2 # Utlöser NameError"print "a3 =", a3 # Lokala namnrummetprint "b =", b # Utlöser NameError"

a = 5function_1()

Page 28: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Importera namnrum

• Om en modul importeras med import modulnamn måste modulens namn användas som “prefix” för att komma åt modulens klasser och funktioner.

• Detta kan undvikas genom att använda from modulnamn import * eller from modulnamn import namn.

>>> import sys>>> sys.version'2.5.1 (r251:54863, Apr 18 2007,08:51:08) [MSC v.1310 32 bit(Intel)]'>>> versionTraceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'version' is notdefined>>> from sys import version>>> version'2.5.1 (r251:54863, Apr 18 2007,08:51:08) [MSC v.1310 32 bit(Intel)]'>>> sys.version'2.5.1 (r251:54863, Apr 18 2007,08:51:08) [MSC v.1310 32 bit(Intel)]'>>> pathTraceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'path' is not defined

Page 29: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Namnkrockar

• Om två moduler definierar samma namn sker en krock i det program som inkluderar båda modulers namnrum.

• Den andra importeringen skriver över gamla definitioner.

• Använd from-formen sparsamt och endast för bibliotek som definierar många klasser och vars namn anses “upptagna”.

Page 30: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

locals och globals

• Python definierar två funktioner som returnerar aktuella lokala och globala variabelnamn som strängindexerade fält.

• Detta kan användas med %-operatorn för elegant utskrift:

# namespaces_04.pydef print_info(first, last, age):

print "Du heter %(first)s %(last)s och är %(age)i år." % locals()

print_info ("Pelle", "Persson", 30)

Page 31: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Objektorienterad programmering

• Begrepp som bör vara kända sedan tidigare enligt förkunskapskraven:

Objekt/InstansKlasserArv

• Python är i grunden ett funktionsorienterat språk, med en objektorienterad påbyggnad.

• Många rester kvar från det funktionsorienterade “ur-Python”.

Page 32: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Terminologi

• Attribut: Ett objekts publika gränssnitt. I Python kan detta syfta på både publika instansvariabler och metoder.

• Argument: Används här för de variabler som skickas in till en metod eller funktion.

• Parameter: Synonym till argument (inparameter) och returvärde (utparameter).

• Instansvariabel: Variabler som är knutna till ett särskilt objekt. I Python är dessa (nästan) alltid publika, vilket gör dem till attribut automatiskt.

• Klassvariabel: Variabler som är knutna till en viss klass, inte till en instans av en klass. Kan existera utan att några instanser finns av klassen.

Page 33: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Klasser

• Definieras med reserverade ordet class.

• Enklast möjliga exempel:

# classes_01.py

class SimpleClass:pass

obj = SimpleClass()print objprint "id: 0x%08X" %id(obj)print dir(obj)

$> python classes_01.py<__main__.SimpleClass instance at 0x00AD3C38>id: 0x00AD3C38['__doc__', '__module__']

Page 34: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

En klass med instansmetoder

• Metoder definieras på samma sätt som funktioner men inuti en klassdefinition.

• Första argumentet till en metod är alltid en referens till objektet som anropat metoden.

• Detta argument kallas av konvention self.

• Instansvariabler skapas som self.variabelnamn.

# classes_02.py

class SimpleClass:def assign_name(self, name):

self.name = name

def print_name(self):print "Jag heter %s." % self.name

girl = SimpleClass()girl.assign_name("Maja")girl.print_name()

boy = SimpleClass()boy.assign_name("Pelle")boy.print_name()

$> python classes_02.pyJag heter Maja.Jag heter Pelle.

Page 35: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Konstruktorer

• Konstruktorer har det reserverade namnet __init__ (dubbla understreck i början och slutet).

• Konstruktorn kan ta argument precis som en vanlig metod.

# classes_03.pyclass SimpleClass:

def __init__(self, name="Okänd"):self.name = name

def print_name(self):print "Jag heter %s." % self.name

girl = SimpleClass("Maja")girl.print_name()unknown = SimpleClass()unknown.print_name()

$> python classes_03.pyJag heter Maja.Jag heter Okänd.

Page 36: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Destruktorer

• Destruktorer har det reserverade namnet __del__ och anropas då ett objekt raderas.# classes_04.py

class SimpleClass:def __del__(self):

print "Objekt 0x%08X tackar för sig." \% id(self)

print "Skapar ett objekt."obj_1 = SimpleClass()obj_1 = 1 # Implicit raderingprint "Skapar ett till."obj_2 = SimpleClass()del(obj_2) #Explicit radering

$> python classes_04.pySkapar ett objekt.Objekt 0x00AD3C88 tackar för sig.Skapar ett till.Objekt 0x00AD3C88 tackar för sig.

Page 37: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Klassvariabler

• Klassvariabler används för att hantera information som hör till klassen snarare än enskilda instanser av klassen.

• Det klassiska exemplet är en variabel som håller reda på hur många instanser av en klass som existerar vid ett givet tillfälle.

Page 38: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Klassvariabler, exempel

# classes_05.py

class SimpleClass:# Klassvariabelinstances = 0

def __init__(self):self.__class__.instances += 1print "Skapar objekt %08X." \

“ instances = %i" \% (id(self), self.__class__.instances)

def __del__(self):print "Objekt 0x%08X tackar för sig." \

% id(self)

objects = []for i in range(5):

objects.append(SimpleClass())

print "Nu finns %i instanser." %objects[0].instances

del objectsprint "Nu finns %i instanser." %SimpleClass.instances

$> python classes_05.pySkapar objekt 00AD3D00. instances = 1Skapar objekt 00AD3D28. instances = 2Skapar objekt 00AD3D50. instances = 3Skapar objekt 00AD3D78. instances = 4Skapar objekt 00AD3DA0. instances = 5Nu finns 5 instanser.Objekt 0x00AD3DA0 tackar för sig.Objekt 0x00AD3D78 tackar för sig.Objekt 0x00AD3D50 tackar för sig.Objekt 0x00AD3D28 tackar för sig.Objekt 0x00AD3D00 tackar för sig.Nu finns 5 instanser.

Page 39: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Omdefiniera klasser

• Vi kan omdefiniera en klass under körning.

• Objekt av den gamla klassen behåller sina metoder.

# classes_06.pyclass SimpleClass:

def __init__(self):print "Skapar en instans av första

versionen."def print_info(self):

print "Jag är en instans av förstaversionen."

obj_1 = SimpleClass()obj_1.print_info()

class SimpleClass:def __init__(self):

print "Skapar en instans av andraversionen."

def print_info(self):print "Jag är en instans av andra

versionen."

obj_2 = SimpleClass()obj_2.print_info()obj_1.print_info()

$> python classes_06.pySkapar en instans av första versionen.Jag är en instans av första versionen.Skapar en instans av andra versionen.Jag är en instans av andra versionen.Jag är en instans av första versionen.

Page 40: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Privata instansvariabler

• Privata instansvariabler och metoder skapas i Python med två inledande understreck.

# private_01.pyclass SimpleClass:

def __init__(self):self.__secret_data = 19

def __secret(self):print "Hemlig data: %i" \

% self.__secret_data

def public_method(self):self.__secret()

obj = SimpleClass()obj.public_method()print obj.__secret_dataobj.__secret()

$> python private_01.pyHemlig data: 19Traceback (most recent call last):

File "private_01.py", line 17, in <module>print obj.__secret_data

AttributeError: SimpleClass instance has noattribute '__secret_data'

• Privata instansvariabler och metoder används mer sällan än i exempelvis C++ och Java.

Page 41: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Angående getters och setters

• I Java används ofta getters och setters för att hantera privata instansvariabler.

• Detta är en praxis som anses onödig i Python, även om det är möjligt.

• Man anser att det är upp till programmeraren att ta ansvar för sin kod och vad den gör. Om man vill komma åt ett objekts inre ska språket inte hindra det.

Page 42: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Arv

• En hierarkisk klasstruktur ökar överskådligheten i komplexa strukturer och tydliggör släktskapet mellan olika objekt.

• Genom arv kan en ny klass återanvända metoder och instansvariabler från en existerande klass.

• Subklasser ärver från superklasser.

Page 43: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel på arv

$> python car_01.pyCar:Jag har gått 100 mil.Taxi:Jag har gått 135 mil.Resan kostar 1755 kr.

# -*- coding: utf-8 -*-# car_01.py

class Car:def __init__(self, distance=0):

self.distance = distance

def __repr__(self):return "Jag har gått %i mil." \% self.distance

class Taxi(Car):def __init__(self, distance=0, fare=10):

Car.__init__(self, distance)self.fare = fare

def total_fare(self):return self.distance * self.fare

def __repr__(self):return Car.__repr__(self) + \"\nResan kostar %i kr." \% self.total_fare()

car = Car(100)taxi = Taxi(135, 13)print "Car:\n", carprint "Taxi:\n", taxiobj_1.print_info()

Page 44: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Multipelt arv

•• Python tillåter multipelt arv. Med andra ord kan en klass ärva från flera klasser som inte är relaterade till varandra.

•• Python använder ”djup-först, vänster-tillhöger” för att bestämma vilken metod som används i en klasshierarki.

class DerivedClassName(Base1, Base2, Base3):<Rad 1>...<Rad N>

Page 45: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Polymorfism

• Polymorfism innebär att samma metod finns definierad på olika nivåer i klasshierarkin.

•• Vilken metod som exekveras avgörs av vilken klass ett objekt har då anropet sker.

Page 46: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Polymorfism i statiska språk

•• I statiska språk som C++ och Java är polymorfism en essentiell konstruktion för att kunna utföra effektiv objektorienterad programmering.

•• För att garantera att alla metoder finns för ett givet objekt måste alla klasser inblandade i ett polymorft objekt definiera samma metoder.

• Virtuella metoder i gemensamma basklasser anger vilket gränssnitt en klass måste implementera för att kunna användas i polymorfin.

Page 47: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Polymorfism i dynamiska språk

• I dynamiska språk är polymorfi inte lika viktigt.

•• Så länge alla inblandade klasser implementerar samma metoder krävs inget släkskap mellan klasserna.

•• Således behövs ingen gemensam basklass för polymorfi, det är ”inbyggt” i det dynamiska idiomet.

•• Anrop till metoder som inte existerar måste hanteras, mer om detta under felhantering senare.

Page 48: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel polymorfi

•• Enklaste exemplet på polymorfi metoden __repr__ som används för att representera ett objekt som en textsträng.

•• Varje klass i Python ärver en __repr__ automatiskt och det stora flertalet överlagrar den för att ge korrekt information om sina objekt.

•• Vid varje anrop till obj.__repr__() styr obj:s klass vilken version av __repr__ som anropas.

Page 49: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Duck typing

• Begreppet används flitigt i Rubyvärlden, men stämmer (nästan) lika väl för Python.

• ”Om det går som en anka och kvackar som en anka måste det vara en anka.”

•• Snarare: ”Om det går som en anka och kvackar som en anka kan Pythontolken gladeligen behandla det som en anka.”

•• Konsekvens: Det spelar större roll vilka metoder ett objekt implementerar än vilken klass det har.

•• Typ är viktigare än klass.

•• Metoders ursprung relativt ointressant.

•• Ett exempel på detta kommer senare.

Page 50: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Operatorer

• Operatorer är tecken som har särskilda betydelser i språket.

•• Dessa inkluderar vanliga matematiska operatorer som +, -, * och /, men även mer programmeringsorienterade operatorer som […] och […]=.

•• Överlagrade operatorer gör det möjligt att använda “normal” matematisk syntax för inbyggda och egna klasser.

Page 51: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Operatorer är syntaktiskt socker

• Operatorer utförs i Python som metodanrop.O

• Observera att a och b spelar olika roller i additionen.

•• a blir anropande objekt medan b blir argument.

•• Således är det a:s klass som avgör vilken __add__-metod som anropas.

•• En konsekvens av detta är att addition inte är en symmetrisk operation i Python. a + b är alltså generellt inte lika med b + a.

>>> a = "Hello ">>> b = "world!">>> a + b'Hello world!'>>> a.__add__(b) # Ekvivalent'Hello world!'

Page 52: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel 1: Addition med en klass

• En överlagrad operator kan utföra vad som helst.

•• Det finns inga krav på att operatorer ska utföra något som påminner om dess matematiska motsvarigheter (även om detta naturligtvis är att rekommendera i de flesta fall).

# -*- coding: utf-8 -*-# operators_01.py

class ClassA:def __init__(self):

self.text = "Jag är en instans av ClassA"

def __add__(self, other):return "Resultat av additionen."

obj_1 = ClassA()obj_2 = ClassA()print obj_1 + obj_2

$> python operators_01.pyResultat av additionen.

Page 53: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel 2: Förvirrande exempel

• Följande exempel definierar en synnerligen värdelös och svårbuggad klass.

•• Den illustrerar dock hur enkelt vi kan skapa en klass vars överlagrade operatorer kan ställa till problem.

# -*- coding: utf-8 -*-# operators_02.py

class StrangeInteger:def __init__(self, value=0):

self.value = value

def __add__(self, other):if self.value == 3233 and other.value == 28937:

import randomreturn StrangeInteger(random(0, 30000))

else:return StrangeInteger(self.value + other.value)

Page 54: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel 3: Strömliknande syntax

• I C++ är <<-operatorn överlagrad för att hantera utskrift.

• Operatorn hanterar ”egentligen” bitvis vänstershift.# -*- coding: utf-8 -*-# operators_03.py

class ExampleStream:def __init__(self, target):

self.target = target

def __del__(self):self.target.close()

def __lt__(self, other):self.target.write(str(other))

cout = ExampleStream(open("output.txt", "w"))cout < "Hello stream output!"cout < 3cout < 3 < 4 # Fungerar inte som tänkt

Page 55: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel 4: Olika klasser

# -*- coding: utf-8 -*-# operators_04.py

class ClassA:def __init__(self, text="Instans av ClassA"):

self.text = text

def __str__(self):return self.text

def __add__(self, other):return ClassA(str(self) + " + " + str(other))

class ClassB:def __init__(self, text="Instans av ClassB"):

self.text = text

def __str__(self):return self.text

def __add__(self, other):return "Addition inte tillåten med ClassB som mottagare."

obj_a = ClassA()obj_b = ClassB()print obj_a + obj_a # => Instans av ClassA + Instans av ClassAprint obj_a + obj_b # => Instans av ClassA + Instans av ClassBprint obj_b + obj_a # => Addition inte tillåten med ClassB som mottagare.

Page 56: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel 5: Indexering

• För att avläsa värden används __getitem__.

• För att sätta värden används __setitem__.

# -*- coding: utf-8 -*-# operators_05.py

import random

class ColorRepo:colors = ["Gul", "Vit", "Svart",

"Gredelin", "Rosa", "Brun"]

def __getitem__(self, index):return self.__class__.colors[index % len(self.__class__.colors)]

cr = ColorRepo()for i in range(5):

print cr[random.randint(0, 30000)]

Page 57: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Matematiska operatorer

Page 58: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Felhantering

• Under utvecklingen av en applikation läggs mycket arbete på att implementera funktionalitet för olika scenarion.

•• Lika viktiga som önskade scenarion är att förbereda för oväntade och/eller oönskade scenarion.

•• Detta kan röra sig om exempelvis felaktig inmatning från användaren eller hårdvaruresurser som är tillfälligt otillgängliga.

Page 59: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Syntaktiska fel

• Syntaktiska fel uppstår då källkoden inte följer Pythons grammatiska regler.

•• Strukturella fel såsom felaktig indentering eller otillåtna kombinationer av kommandon.

•• Pythontolken läser igenom hela filen innan programmet exekveras.

•• Således upptäcks syntaktiska fel redan innan programmet körs.

Page 60: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Undantag (exceptions)

•• Associationen till fel olycklig.

•• Tänk på undantag som exceptionella händelser, något som inte är precis som i huvudscenariot.

•• Inte heller detta är en bra definition.

•• Huvudpoäng: Undantag är en viktig och naturlig del av Pythonprogrammeringen.

Page 61: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Inbyggda undantag

•• Undantag är objekt med klassen Exception som gemensam superklass.

•• Vanliga undantag är LookupError, ImportError och TypeError. Se Programmering i Python 11.3.1 för en lista på andra inbyggda undantag.

Page 62: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Hantera undantag

• Undantag fångas med en try-except-konstruktion (Motsvarar Javas try-catch).# -*- coding: utf-8 -*-# exceptions_01.py

while True:try:

x = int(raw_input("Skriv in ett tal: "))break

except ValueError:print "Inte ett giltigt tal. Försök igen."

$> python exceptions_01.pySkriv in ett tal: fInte ett giltigt tal. Försök igen.Skriv in ett tal: kli89hInte ett giltigt tal. Försök igen.Skriv in ett tal: 25

Page 63: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Hantera olika undantag

•• Ett try-block kan ha olika except-klausuler som hanterar olika fel.# -*- coding: utf-8 -*-# exceptions_02.py

while True:try:

d = int(raw_input("Skriv in täljaren: "))n = int(raw_input("Skriv in nämnaren: "))print "Resultat = %i" % (d / n)break

except ValueError:print "Inte ett giltigt tal. Försök igen."

except ZeroDivisionError:print "Division med noll. Försök igen."

$> python exceptions_02.pySkriv in täljaren: fInte ett giltigt tal. Försök igen.Skriv in täljaren: 4Skriv in nämnaren: 0Division med noll. Försök igen.Skriv in täljaren: 6Skriv in nämnaren: 2Resultat = 3

Page 64: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Framkalla undantag

• Undantag kan framkallas manuellt med kommandot raise.

•• Det är ingen skillnad mellan undantag som framkallats manuellt och undantag som uppkommit genom exekvering av kod.

•• raise kan användas för att få ett undantag att ”bubbla vidare” då det behandlats. Se nästa slide.

# -*- coding: utf-8 -*-# exceptions_03.py

try:raise ValueError("Hej", 14, "Eget meddelande")

except ValueError, (nonsense, err_no,err_msg):print "Undantag uppstod:"print "err_no = %s\nerr_msg = %s" % \(err_no, err_msg)

$> python exceptions_03.pyUndantag uppstod:err_no = 14err_msg = Eget meddelande

Page 65: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Undantagsflöden

•• Undantag ”bubblar upp” i funktionsanrop.

•• Om ett undantag behandlas av en exceptklausul anses det som hanterat.

•• Exekveringen fortsätter efter det except-block som hanterat felet (inte nödvändigtvis där undantaget uppstod).

Page 66: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel på undantagsflöden

# -*- coding: utf-8 -*-# exceptions_04.py

def function_a():try:

function_b()except ValueError:

print "Undantag uppstod."print "Detta skrivs ut efter att undantaget"print "hanterats i function_a"raise StandardError("Detta kommer inte hanteras.")

def function_b():try:

function_c()except KeyError:

passprint "Detta skrivs inte ut."

def function_c():raise ValueError

function_a()

$> python exceptions_04.pyUndantag uppstod.Detta skrivs ut efter att undantagethanterats i function_aTraceback (most recent call last):

File "exceptions_04.py", line 23, in<module>function_a()

File "exceptions_04.py", line 11, in function_araise StandardError("Detta kommer inte hanteras.")

StandardError: Detta kommer inte hanteras.

Page 67: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Undantag som kontrollmekanismer

• Undantag kan användas för att ersätta if-satser.

•• Exempel: Istället för att kontrollera om ett objekt stödjer en viss metod anropas metoden inom ett try-block. Om anropet genererar ett AttributeError vet man att metoden inte stöds och lämpliga åtgärder kan utföras.

•• Om man har många men ovanliga scenarion att kontrollera kan detta designsätt leda till betydande prestandaökningar.

Page 68: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Definiera egna undantag

# -*- coding: utf-8 -*-# exceptions_05.py

class MyOwnException(Exception):def __init__(self, arg):

self.arg = arg

def __str__(self):return "Undantag med argument '%s' uppstod." % self.arg

raise MyOwnException("exempelargument")

$> python exceptions_05.pyTraceback (most recent call last):

File "exceptions_05.py", line 10, in <module>raise MyOwnException("exempelargument")

__main__.MyOwnException: Undantag med argument 'exempelargument' uppstod.

Page 69: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Filhantering

• Filer är ett samlingsnamn för data som sparats någon annanstans än i datorns primärminne.

•• Detta kan vara exempelvis en lokal hårddisk, en CD-skiva eller en resurs på nätverket.

•• Man försöker generellt erbjuda ett standardiserat gränssnitt för hantering av filer oavsett vilken typ den aktuella filen har (jämför med Javas olika strömmar).

Page 70: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Öppna och läsa från en fil

• En fil öppnas med funktionen open.# -*- coding: utf-8 -*-# io_01.py

f = open("newfile.txt", "r") # Öppna filenprint f.read() # Läs in hela filen

Page 71: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Läsa in delar av en fil

# -*- coding: utf-8 -*-# io_01.py

f = open("newfile.txt")for row in f.readlines():

print row,

f.close()f = open("newfile.txt")print f.read(8)print f.read(5)

$> python io_02.pyDetta är textrad 1.Detta är textrad 2.Detta är textrad 3.Detta är textrad 4.Detta är text

Page 72: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Skriva till en fil

# -*- coding: utf-8 -*-# io_03.py

f = open("newfile.txt", "w")f.write(str(3) + "\n")f.write(str([1,2,3]) + "\n")f.write(str({"name":"Kalle"}) + "\n")f.close()

f = open("newfile.txt", "a")f.write("Denna rad läggs till.")f.close()

f = open("newfile.txt")print f.read()f.close()

$> python io_03.py3[1, 2, 3]{'name': 'Kalle'}Denna rad läggs till.

Page 73: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Serialisering

•• Att spara objekt som strängar kan vara opraktiskt för komplexa objekt.

•• Serialisering är en teknik som automatiskt omvandlar ett Pythonobjekt till en binär sekvens och sparar den till en fil.

•• I Python definieras serialisering i modulen pickle.

Page 74: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Exempel, pickle

# -*- coding: utf-8 -*-# test_class.py

class TestClass:def __init__(self, data):

self.data = datadef __str__(self):

return str(self.data)

# -*- coding: utf-8 -*-# serialisation_01.py

from test_class import TestClassimport cPickle

obj = TestClass(["Hello", "world", "!"])cPickle.dump(obj, open("serial_object.p", "w"))

# -*- coding: utf-8 -*-# serialisation_02.py

from test_class import TestClassimport cPickle

obj = cPickle.load(open("serial_object.p"))print obj

Page 75: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

shelve

• Modulen shelve använder pickle för att skapa strängindexerade fält där objekten lagras på disk.

•• När shelve-databasen skapats används den precis som ett vanligt strängindexerat fält.

# -*- coding: utf-8 -*-# serialisation_03.py

from test_class import TestClassimport shelve

db = shelve.open("test_objects")db["first"] = TestClass("Första objektet")db["second"] = TestClass("Andra objektet")db["something else"] = "Ett objekt av en annan typ."db.close()

db = shelve.open("test_objects")for key, value in db.items():

print "Nyckeln '%s' innehåller värdet '%s'" % \(key, value)

Page 76: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Alternativ till shelve

• Det finns många alternativ till att lagra objekt med shelve, exempelvis XML och YAML.

•• XML beskrivs i Programmering i Python kapitel 18.

# -*- coding: utf-8 -*-# yaml_01.py

import yamlstorage = yaml.load("""name: Kalle Karlssonnationality: Swedishdimensions: [187, 82]age: 30description: En glad kille.siblings:- Klara- Maja- Pelle""")

print storageprint yaml.dump(storage)

$> python yaml_01.py{'description': 'En glad kille.', 'name': 'Kalle Karlsson', 'nationality': 'Swedish', 'siblings': ['Klara', 'Maja', 'Pelle'], 'age': 30, 'dimensions': [187, 82]}age: 30description: En glad kille.dimensions: [187, 82]name: Kalle Karlssonnationality: Swedishsiblings: [Klara, Maja, Pelle]

Page 77: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Träning

• Träning är något som är en självklar del av många discipliner: Musik, idrott och matematik.

•• Inom programmeringen får däremot träning betydligt mindre fokus.

•• Ofta lär vi oss saker under tiden vi utför skarpa projekt.

•• Programmering är ett enormt område men det hindrar inte att man övar på grundläggande bitar som återkommer i många sammanhang.

•• Om man har god kontroll över ett språk minskar tröskeln för att använda nya moduler.

•• Detta gäller även programmering i stort (lättare att lära sig ett nytt språk om man kan flera sedan tidigare).

Page 78: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Vad utgör god träning?

• Tid utan störningar.

•• En väldefinierad "enkel" uppgift.

•• Möjlighet att försöka så många gånger som krävs för att lyckas.

•• Ingen oro för att göra misstag.

•• Kort väg från test till resultat.

•• Inga krav.

•• Trial-and-error är bra men blir verkningslöst i för komplexa sammanhang.

•• "Du vet att en träningssession varit lyckad om du går från den med kunskap du inte hade innan."

Page 79: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Code Kata

• Code Kata har vuxit ur behovet av väldefinierade "träningsproblem" som är mer krävande än vanliga "läroboksuppgifter".

•• Ordet kata är en övning i karate där en övning repeteras gång på gång, med gradvis förbättring, tills den bemästras till fulländning.

•• Varje kata är beräknad att ta 30-60 minuter att utföra.

•• Vissa bygger på att lösa samma problem på flera olika sätt.

•• Andra är friare och leder sällan till ett precist svar utan (förhoppningsvis) till en större förståelse för programmering som färdighet och konstart.

• Katorna finns på http://www.codekata.com.

Page 80: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Code Kata 5: Bloom-filter

• Bloom-filter är en metod för att testa medlemskap i en mängd.

•• Filtret skapades 1970 av Burton Bloom (Space/time trade-offs in hash coding with allowable errors.Communications of ACM, pages 13(7):422-426, July 1970.)

•• Filtret kräver mindre tid och lagringsutrymme än en exakt metod men kan ge "falska träffar".

•• Metoden ger inga "falska missar".

•• Referenser till matematiska bakgrunden finns på katans hemsida.

Page 81: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Uppgift (frivillig)

• Katans uppgift är att implementera ett Bloom-filter.

•• Ordlistor för testning finns på hemsidan.

•• Läs gärna igenom övriga kator.

•• Det rekommenderas varmt att försöka göra så många kator som möjligt, någon gång i ens utbildning (och även senare).

•• Att göra katorna är ett bra sätt att snabbt sätta sig in i ett nytt språk. Tillsammans täcker de stora delar av ett språks grundläggande delar.

Page 82: Föreläsning 3 och 4 - Uppsala University...greeting(45) # Fel resultat $> python function_04.py Hej Okänd. Du är 20 år gammal. Hej Pelle. Du är 20 år gammal. Hej 45. Du är

Grundläggande Python klart!

• Nu kan ni Python!!!

•• Nästa föreläsning börjar vi titta på programpaket som utför intressanta saker.