Dataabstraktion TDDD73 Funktionell och imperativ programmering i Python Föreläsning 12 Peter Dalenius Institutionen för datavetenskap 2014-11-19
Översikt Vad är abstraktion? Vad är en abstrakt datatyp? Hur kan man designa och implementera abstrakta datatyper? Exempel på abstrakt datatyp: symbolisk derivering Sätt att konstruera sammansatta datatyper Introduktion till almanackan och laborationsomgång 6 2
Abstrakt Teoretisk, konstruerad, overklig, svårfattlig, dunkel, diffus, akademisk Konkret Verklig, påtaglig, faktisk, åskådlig, existerande, tydlig, gripbar 3
4
Olika typer av abstraktion 1. Låt s vara 0 2. För varje tal n i listan x summera_lista låt s vara s + n 3. Returnera s Årtal Månad Dag Nummer personnummer Procedurabstraktion Dataabstraktion 5
Defintion av datatyp (igen) En datatyp är en väldefinierad sorts information som ett datorprogram kan använda. Datatypen talar om vilka dataobjekt som ingår i typen (vilken domän som typen har) samt vilka operationer som är tillåtna. Datatypen svarar alltså på frågorna: Hur ser objekten ut? Vad kan man göra med dem? 6
Datatyper på olika nivåer Allmänna datatyper (stack, kö, tabell, bråk, graf) Min programvara Abstrakta datatyper Tillämpningsnära datatyper (personer, fordon, kurser, schema, klockslag) Programspråk (heltal med oändlig precision, strängar, listor, ) Hårdvara (bit, heltal, flyttal, ) 7
Datatypens definitionsmängd Ändlig T.ex. sanningsvärden {True, False} Oändlig T.ex. heltal Sammanlagd T.ex. tal (Number i Python) som en union av heltal, flyttal och komplexa tal. Rekursivt definierad T.ex. ett binärt sökträd kan vara ett tomt träd, ett löv eller en nod som innehåller två binära sökträd. 8
Primitiva operationer på datatyper De primitiva operationerna utgör datatypens gränssnitt (eng. interface) gentemot resten av programkoden. Några exempel på typer av primitiver: Konstruktorer (eng. constructors) för att skapa objekt Selektorer (eng. selectors) för att plocka ut delarna Igenkännare (eng. recognizers) för att känna igen objekt av viss datatyp eller objekt med särskilda egenskaper. Iteratorer (eng. iterators) för att bearbeta alla elementen i ett objekt, ofta med hjälp av högre ordningens funktioner Jämförare (eng. comparator) för att kontrollera när objekt är lika Modifikatorer (eng. modifiers) för att ändra elementen i ett objekt 9
Exempel: Symbolisk derivering Deriveringsregler =1 om u = x (+) = + =0 om u ej är en funktion av x ( ) = + Exempel +4 =1+0=1 3+4 2+1 = 3+4 2+ 2+1 3=12+11 10
Exempel: Symbolisk derivering def derive(expr, var): if expr == var: return 1 elif isinstance(expr, str) or isinstance(expr, int): return 0 elif expr[1] == '+': return [derive(expr[0], var), '+', derive(expr[2], var)] elif expr[1] == '*': return [[expr[0], '*', derive(expr[2], var)], '+', [derive(expr[0], var), '*', expr[2]]] else: raise Exception("Invalid expression!") 11
Exempel: Symbolisk derivering >>> derive('x', 'x') 1 >>> derive(['x', '+', 5], 'x') [1, '+', 0] # 1 >>> derive([4, '*', 'x'], 'x') [[4, '*', 1], '+', [0, '*', 'x']] # 4 Denna lösning är representationsberoende. Programkod som relaterar till hur vi har valt att lagra de matematiska uttrycken är sammanblandad med programkod som behandlar algoritmen för symbolisk derivering. En av de stora poängerna med att införa abstrakta datatyper är vi vill gömma informationen om hur data är representerat (eng. information hiding). 12
Arbetsmetodik 1. Identifiera datatyper Studera tillämpningsområdet och karaktärisera den information som hanteras. För sammansatt information, bestäm hur de ingående delarna relaterar till varandra. 2. Bestäm primitiver Se olika typer på föregående bild. 3. Bestäm representation För varje datatyp, bestäm hur de enskilda objekten ska representeras (i termer av de datatyper som finns i det språk som används) 4. Definiera primitiver Implementera. 13
1. Identifiera datatyper Vilka delar består ett matematisk uttryck av (så långt vi orkar specificera i det här exemplet)? Ett uttryck kan vara en konstant, en variabel eller ett sammansatt uttryck. Ett sammansatt uttryck består i sin tur av två uttryck med en operator emellan. Orden i fetstil ovan är våra abstrakta datatyper. Ofta kan fler detaljer behöva specificeras, men i det här exemplet nöjer vi oss så här. 14
2. Bestäm primitiver Var och en av de fem datatyperna behöver åtminstone en basuppsättning primitiver: konstruktor (som skapar ett objekt från dess delar), selektorer (som plockar ut de olika delarna) och igenkännare. Det är dock inte säkert att alla dessa primitiver är nödvändiga för varje datatyp i just det exempel vi ska implementera. 15
3. Bestäm representation konstant = ett vanligt tal så som det skrivs i Python variabel = en sträng i Python som innehåller bokstäver operator = en sträng i Python som innehåller någon av symbolerna + eller * sammansatt uttryck = en lista bestående av tre element: två uttryck med en operator mellan sig 16
4. Definiera primitiver # Constant def isconstant(obj): """Check if argument is a constant.""" return isinstance(obj, int) or isinstance(obj, float) def make_constant(n): """Make a constant from a number.""" return n # Variable def isvariable(obj): """Check if argument is a variable.""" return isinstance(obj, str) def same_variable(var1, var2): """Check if two variables have the same name.""" return var1 == var2 docstring 17
4. Definiera primitiver def issum(obj): """Check if argument is a binary addition expression.""" return isinstance(obj, list) and len(obj) == 3 and obj[1] == '+' def make_sum(left, right): """Make a binary addition expression.""" return [left, '+', right] def isproduct(obj): """Check if argument is a binary multiplication expression.""" return isinstance(obj, list) and len(obj) == 3 and obj[1] == '*' def make_product(left, right): """Make a binary multiplication expression.""" return [left, '*', right] def arg1(expr): """Return the first subexpression.""" return expr[0] def arg2(expr): """Return the second subexpression.""" return expr[2] 18
Symbolisk derivering (abstraherad version) def derive(expr, var): if isconstant(expr): return make_constant(0) elif isvariable(expr): if same_variable(expr, var): return make_constant(1) else: return make_constant(0) elif issum(expr): return make_sum(derive(arg1(expr), var), derive(arg2(expr), var)) elif isproduct(expr): return make_sum(make_product(arg1(expr), derive(arg2(expr), var)), make_product(derive(arg1(expr), var), arg2(expr))) else: raise Exception("Invalid expression!") 19
Sätt att konstruera sammansatta datatyper Många sammansatta abstrakta datatyper liknar varandra strukturellt och därför kan det vara bra att försöka hitta överordnade begrepp för att beskriva dem. Följande diskretmatematiska begrepp brukar användas för att karaktärisera olika sorters sammansatta datatyper: Tupel Ändlig avbildning Sekvens Mängd 20
Tupel Begrepp Vad är det? Tupel En datatypmed ett fixt antal element där varje element har en given datatyp, dvs. ordningen mellan elementen spelar rolloch elementen i sig har olika betydelser. Hur beskriver videt? <datatyp 1, datatyp 2,, datatyp n > Exempel Motsvarighet i Python datum = <år, månad, dag> tuple 21
Ändlig avbildning Begrepp Vad är det? Ändlig avbildning (eng. finite mapping) Hur beskriver videt? [data 1, data 2,, data n ] En datatypmed ett fixt antal element av samma datatyp där ordningen mellan elementen egentligen inte spelar så stor roll(enbart om indexmängden är ordnad). Exempel veckoschema= [dagschema 1, dagschema 7 ] Motsvarighet i Python list(även om Python-listor är mer generösa) dict(om indexmängden är annat än heltal) indexmängd (ofta heltal) definitionsmängd 22
Sekvens Begrepp Vad är det? Hur beskriver vi det? Exempel Motsvarighet i Python Sekvens En datatypmed ett valfritt antal element av samma datatyp där ordningen mellan elementen spelar roll. {{datatyp}}* om det är okej med tomma sekvenser {{datatyp}}+ om sekvensen måste innehålla något utbildningsprogram = {{kurs}}* list 23
Mängd Begrepp Vad är det? Hur beskriver vi det? Exempel Motsvarighet i Python Mängd En datatypmed ett valfritt antal element av samma datatypdär ordningen mellan elementen inte spelar roll. {datatyp} studieresultat = {kurs} set 24
Laborationsomgång 6: Almanackan I laborationsomgång 6 kommer ni att få arbeta med ett större kodexempel som innehåller ett almanackssystem. Almanackan kan användas för att boka och hålla reda på aktiviteter. Den är uppbyggd av ett stort antal abstrakta datatyper. Almanackan är en klassisk laborationsuppgift som har används i grundkurser i många år. Själva koden i almanackan är mycket enkel och innehåller inga Python-konstruktioner som ni inte redan kan. Även om koden är enkel kan det dock ta ett tag att sätta sig in i tankesättet. 25
Elementära abstrakta datatyper hour (ett positivt heltal) minute (ett positivt heltal) day (ett positivt heltal) month (en sträng med namnet på en månad) subject (en sträng som beskriver ett mötes karaktär) 26
Sammansatta abstrakta datatyper time = <hour, minute> span = <time, time> appointment = <span, subject> calendar_day = {{appointment}}* calendar_month = [calendar_day,...] calendar_year = [calendar_month,...] duration = <hour, minute> date = <month, day> 27
Primitiva funktioner def new_hour(h): "Python integer -> hour" def is_hour(object): "Python object -> truth value" Olika typer av primitiva funktioner: Konstruktorer Selektorer Igenkännare def new_minute(m): "Python integer -> minute" def is_minute(object): "Python object -> truth value" def get_integer(hour_minute): "hour U minute -> Python integer" Primitivernas signaturer beskriver vilka datatyper som förväntas som indata respektive utdata. 28
Grundläggande typmaskineri def attach_tag(type, object): "calendar type tag x Python object -> calendar object" return (type, objekt) def strip_tag(object): "calendar object -> Python object" if isinstance(object, tuple): return object[1] def get_tag(object): "calendar object -> calendar type tag" if isinstance(object, tuple): return object[0] 29
Krav på primitiva funktioner I almanackssystemet har vi ställt upp följande krav på våra primitiva funktioner: De ska alltid kontrollera att argumenten är av rätt typ. Ett värde som en konstruktor skapar ska alltid vara giltigt. De ska alltid kontrollera att restriktioner och beroenden mellan delar är uppfyllda (t.ex. att ett klockslag inte kan ha en timme större än 23, även om en timme i sig kan vara större än så). 30
Implementation av primitiva funktioner def new_hour(h): "Python integer -> hour" ensure(h, lambda h: isinstance(h, int) and 0 <= h) return attach_tag('hour', h) def is_hour(object): "Python object -> truth value" return get_tag(object) == 'hour' def get_integer(hour_minute): "hour U minute -> Python integer" ensure(hour_minute, lambda x: is_hour(x) or is_minute(x)) return strip_tag(hour_minute) 31
Almanackans Python primtiver Almanackan Tillämpning Abstraktionslager System som använder sig av vår almanacka create book show show_free load save Rutiner för att boka och avboka möten samt hantera almanackor new_hour is_hour get_integer new_duration length_of_span Rutiner för att kapsla in och kontrollera almanacksdata [] + - () * / Pythons interna rutiner och interna representation av t.ex. heltal och listor 32
Uppgifter 6A: Förbättra några funktioner som bryter mot abstraktionen. 6B: Implementera en ny datatyp. 6C: Implementera allt som behövs för att avboka möten. 6D: Implementera allt som behövs för att kontrollera lediga tider, inklusive testrutiner. 6E: Implementera kontroll av gemensamma lediga tider (frivillig uppgift). Mer praktisk introduktion till almanackan kommer på lektion 5. 33
Sammanfattning Abstrakta datatyper Arbetsmetodik Primitiva operationer (konstruktor, selektor, ) Begrepp för att beskriva sammansatta abstrakta datatyper (tupel, ändlig avbildning, sekvens, mängd) Exempel: Derivering Laborationsomgång 6: Almanackan 34
Bildkällor: http://commons.wikimedia.org/wiki/file:geely_assembly_line_in_beilun,_ningbo.jpg http://commons.wikimedia.org/wiki/file:final_assembly_3.jpg http://commons.wikimedia.org/wiki/file:us_army_51725_watervliet_arsenal_apprentices_start_at_the_ground_floor.jpg http://commons.wikimedia.org/wiki/file:wmuk_february_2012_board_meeting.jpg http://commons.wikimedia.org/wiki/file:comit%c3%a9_de_ministros_de_infraestructura,_ciudad_y_territorio.jpg www.liu.se