Klasser og Objekter i Python Uge 46 Learning Python: kap 15-16, 19-22.
Klasser og objekter En klasse beskriver en klump af samhørende funktioner og variable En klasse er en beskrivelse. En kage form Klassens objekter er instanser af klassen. De enkelte kager En programudførelse indeholder objekter, ikke klasser
Samlingsmønstret Rekursiv definition Samling ::= {Del}* Del ::= Simpel Samling Samling Del Del Samling Del Del
Nedarvning Begge arver navn fra overklas sen Samling tilføjer nye ting Subklassen arver variable og funktioner fra superklassen Simpel: navn str Samling: navn dele str tilføj fjern hent Simpel bevarer superklassens str Samling overskriver superklassens str
init og andre funktioner class Del: def init (self, navn): self.navn = navn def str (self, niveau = 1): text = '\n'+ niveau *''+'('+ self.navn + ')' return text class Samling(Del): def init (self, navn, dele = None): Del. init (self, navn) self.dele = dele def tilfoej(self,endel): self.dele.append(endel) def fjern(self,endel): if endel in self.dele: self.dele.remove(endel) def hent(self,delnavn): for d in self.dele: if d.navn == delnavn: return d return None def str (self, niveau = 1): text = '\n'+ niveau *''+'('+ self.navn for endel in self.dele: text += endel. str (niveau+1) text += '\n'+ niveau *''+')' return text class Simpel(Del): def init (self, navn): Del. init (self, navn) initialisering funktioner superklasse subklasse subklasse
Dannelse af objekter Inits parametre bil = Samling('bil',[Samling('karosseri'),Samling('hjul'),Samling('motor')]) bil.hent('karosseri').tilfoej(simpel('tag')) bil.hent('karosseri').tilfoej(simpel('doere')) bil.hent('karosseri').tilfoej(simpel('bund')) bil.hent('hjul').tilfoej(simpel('venstre forhjul')) bil.hent('hjul').tilfoej(simpel('venstre forhjul')) bil.hent('hjul').tilfoej(simpel('hoejre forhjul')) bil.hent('hjul').tilfoej(simpel('venstre baghjul')) bil.hent('hjul').tilfoej(simpel('hoejre baghjul')) bil.hent('motor').tilfoej(simpel('stempler')) bil.hent('motor').tilfoej(simpel('karburator')) print bil Kald af hjulsamlingens tiltøj-funktion
Output ) ) (bil (karosseri (Tag) (Doere) (Bund) (hjul (venstre forhjul) (venstre forhjul) (hoejre forhjul) (venstre baghjul) (hoejre baghjul) (motor (stempler) (karburator) ) )
Definition af klasser: klassenavn Class <klassenavn>(<evt. superklasse>): <init-funktionen> <funktioner der tilhører klassen> superklasse class Samling(Del): 'repræsenterer en samling af dele, enten samlinger eller simple ' def init (self, navn, dele = None): Del. init (self, navn) self.dele = dele def tilfoej(self,endel): if self.dele == None: self.dele = [] self.dele.append(endel) def fjern(self,endel): if self.dele == None: self.dele = [] if endel in self.dele: self.dele.remove(endel) def hent(self,delnavn): for d in self.dele: if d.navn == delnavn: return d return None def str (self, niveau = 1): 'giver en textuel repræsentation af klassen str gør det muligt at printe klassen direkte ' text = '\n'+ niveau *''+'('+ self.navn for endel in self.dele: text += endel. str (niveau+1) text += '\n'+ niveau *''+')' return text Init funktionen Funktioner der tilhører klassen
Check om det er rigtigt: Introspektion Python indeholder en række funktioner der giver direkte adgang til dens indvolde Objekt. dict : en dictionary der gemmer objektets attributter og værdier Dir(object): returnerer alle de attributter og metoder der er knyttet til objektet.
Introspection def introspect(self): text = 'Dictionary: ' text += '\n'+ str(self. dict ) text += '\n'+'attributes and functions: ' text += '\n'+ str(dir(self)) return text
Eksempel Bil (Samling): Dictionary: {'dele': [< main.samling instance at 0x00FC2BE8>, < main.samling instance at 0x00FC2CD8>, < main.samling instance at 0x00FC2D00>], 'navn': 'bil'} Attributes and Functions : Tag (Simpel): [' doc ', ' init ', ' module ', ' str ', 'dele', 'fjern', 'hent', 'introspect', 'navn', 'tilfoej'] Dictionary: {'navn': 'Tag'} Attributes and Functions : [' doc ', ' init ', ' module ', ' str ', 'introspect', 'navn'] Nedarvede fra Python Brugerdefinerede
Generering af klasser <klassenavn>(<inits parametre undtagen self>) Klasse definition class Simpel(Del): def init (self, navn): Del. init (self, navn) Generering af klasse Forhjul = Simpel('venstre forhjul') init kaldes automatisk når klassen genereres Simpel s init kalder superklassens init Husk at give den parametren self med!!
Self self henviser til det nydannede objekt Når man i klassedefinitionen vil henvise til objektets egne funktioner eller variable skal det ske via self def getname(self): return self.name
Med og uden self class Samling(Del): def init (self, navn, dele): Del. init (self, navn) self.dele = dele stelnummer = 100 Stelnummer er blot en lokal variabel i init der forsvinder når funktionen har kørt. Dele er derimod fast knyttet til objektet >>> bil.dele [< main.simpel instance>, < main.samling instance >, < main.simpel instance >] >>> bil.stelnummer Traceback (most recent call last): File "<pyshell#7>", line 1, in? bil.stelnummer AttributeError: Samling instance has no attribute 'stelnummer' >>>
Self bruges også til at referere til objektets egne funktioner class Eksempel: def init (self,enliste): self.minliste = enliste def summer(self): resultat = 0 for i in self.minliste: resultat += i return resultat def udskrivsum(self): print self.summer() Eksempel -minliste +summer() +udskrivsum() etelement = Eksempel([1,2,3,4]) etelement.udskrivsum() Resultat: 10 >>>
Udeladelse af self def udskrivsum(self): print summer() Python ved ikke hvad summer refererer til: print summer() NameError: global name 'summer'is not defined
Benyttelse af klasser Man kan godt bruge klasser s funktioner (ubundne funktioner) uden at lave en instans, men så skal de have en instans som argument: etelement = Eksempel([1,2,3,4]) Eksempel.udskrivSum(etElement)
Hele Python består af objekter >>> L = [1,2,3] >>> L.append(4) >>> L [1, 2, 3, 4] >>>
Relationer mellem objekter Der er en én-mange relation mellem en samling og dens dele En relation er et abstrakt begreb der kan implementeres på mange måder. SQL: som en relation Python: som en liste af objekter
SQL Helhedens primærnøgle benyttes som fremmednøgle i delen Del Samling
Python class Samling(Del): def init (self, navn, dele): Del. init (self, navn) self.dele = dele Helheden har en liste over de objekter der repræsenterer dens dele
OOogSQL Overskriver overklassens printcontents
OOogSQL OOogSQL repræsenterer tabeller og udtræk af en database der selv kan repræsentere fænomener i problemområdet Andre programtekster repræsenterer problemområdet direkte
Introspektion Table Dictionary: {'values': [['1111111111', 'Jeppe Boegh', 'Andersen', 'Thorsgade 20', '8410', 'dreng', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114'], ['1111111114', 'Lotte Boegh', 'Andersen', 'Thorsgade 20', '8410', 'pige', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114'], ['1111111115', 'Stine', 'Jacobsen ', 'Thorsgade 20', '8410', 'pige', ', '86379790', 'baltica', ', '1111111116', '1111111114']], 'columnnames': ['cpr', 'firstname', 'lastname', 'address', 'city', 'gender', 'email', 'phone', 'insurance', 'hasfather', 'hasmother', 'hasdoctor'], 'rows': [< main.row instance at 0x0127B508>, < main.row instance at 0x01281DF0>, < main.row instance at 0x012D1648>], 'tablename': 'Child', 'primarykey': 'cpr'} Attributes and Functions: [' doc ', ' init ', ' module ', 'columnnames', 'getprimarykey', 'getrow', 'introspect', 'makehtmltable', 'primarykey', 'printcontents', 'rows', 'tablename', 'values']
Introspection Row Dictionary: {'values': ['1111111111', 'Jeppe Boegh', 'Andersen', 'Thorsgade 20', '8410', 'dreng', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114'], 'columnnames': ['cpr', 'firstname', 'lastname', 'address', 'city', 'gender', 'email', 'phone', 'insurance', 'hasfather', 'hasmother', 'hasdoctor'], 'tablename': 'Child', 'primarykey': 'cpr'} Attributes and Functions : [' doc ', ' init ', ' module ', 'columnnames', 'delete', 'get', 'getprimarykey', 'insert', 'introspect', 'makehtmltable', 'primarykey', 'printcontents', 'put', 'putallvalues', 'tablename', 'update', 'values']
Introspection Temporary Dictionary: {'columnnames': ['cpr', 'firstname', 'lastname'], 'values': (('1111111115', 'Stine', 'Jacobsen '),)} Attributes and Functions : [' doc ', ' init ', ' module ', 'columnnames', 'introspect', 'makehtmltable', 'printcontents', 'values']
Persistent Omdefinering af Reference til mig selv overklassens class Persistent(SQL): funktion 'Abstract class ' def init (self, tablename, values): self.primarykey = database.getprimarykey(tablename) Overklassens navn self.tablename = tablename columnnames = database.getcolumnnames(tablename) SQL. init (self, columnnames, values) def printcontents(self): 'prints the data of the object ' print 'Table name: '+self.tablename print 'Primary key: '+ self.primarykey Genbrug af SQL.printContents(self) overklassens def getprimarykey(self): funktioner 'returns the primary key ' return self.primarykey
Table class Table(Persistent): def init (self, tablename): values = database.findrecords(tablename,[]) valuelist = [] Persistent. init (self,tablename, values) #insert a list of Row-instances corresponding to the values rows =[] primarykey = self.primarykey i = self.columnnames.index(primarykey) for v in self.values: thekey = v[i] rows.append(row(tablename,thekey)) self.rows = rows def getrow(self,thekey): 'returns a row-instance whose primary key = thekey if none exists, returns None ' primarykey = self.getprimarykey() for r in self.rows: Self.getPrimaryKey() er if r.get(primarykey) == thekey: return r nedarvet fra overklassen return None def printcontents(self): 'prints the data of the object ' print 'Table name: '+self.tablename print 'Primary key: '+ self.primarykey print 'Values : \n'+ str(self.values) print 'Components: ' for c in self.components: c.printcontents()
Brug af OOogSQL 1 fetch a row from Child with primary key 1111111111, change the first name to Jeppe and store it, fetch the row again to see if the change worked arow = Row('Child','1111111111') arow.put('firstname','jeppe') arow.update() arow = Row('Child','1111111111') arow.printcontents() Resultat: Table name: Child Primary key: cpr Column names: ['cpr', 'firstname', 'lastname', 'address', 'city', 'gender', 'email', 'phone', 'insurance', 'hasfather', 'hasmother', 'hasdoctor'] Values: [['1111111111', 'Jeppe', 'Andersen', 'Thorsgade 20', '8410', 'dreng', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114']]
Brug af OOogSQL 2 restore the first name, print a html version of the row arow.put('firstname','jeppe Boegh') arow.update() print arow.makehtmltable()
Resultat <table width="75%" border="1"> <tr> <td>cpr</td> <td>firstname</td> <td>lastname</td> <td>address</td> <td>city</td> <td>gender</td> <td>email</td> <td>phone</td> <td>insurance</td> <td>hasfather</td> <td>hasmother</td> <td>hasdoctor</td> </tr> <tr> <td>1111111111</td> <td>jeppe Boegh</td> <td>andersen</td> <td>thorsgade 20</td> <td>8410</td> <td>dreng</td> <td></td> <td>86379790</td> <td>baltica</td> <td>1111111112</td> <td>1111111113</td> <td>1111111114</td> </tr> </table>
Brug af OOogSQL 3 make a new empty row-object, insert values into the object arow = Row('Child') valuelist = ['1111111111', 'Jeppe Boegh', 'Andersen', 'Thorsgade 20', '8410', 'dreng', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114'] arow.putallvalues(valuelist) arow.printcontents() Resultat Table name: Child Primary key: cpr Column names: ['cpr', 'firstname', 'lastname', 'address', 'city', 'gender', 'email', 'phone', 'insurance', 'hasfather', 'hasmother', 'hasdoctor'] Values: ['1111111111', 'Jeppe Boegh', 'Andersen', 'Thorsgade 20', '8410', 'dreng', ', '86379790', 'Baltica', '1111111112', '1111111113', '1111111114']
Brug af OOogSQL 4 create a selection of all children that live at the same address as their mother' SQLordre = 'SELECT Child.cpr, Child.firstname, Child.lastname FROM Child, Person WHERE Child.hasMother = Person.cpr AND Child.address = Person.address ' aselection = Temporary(['cpr','firstname','lastname'],SQLordre) aselection.printcontents() Resultat Column names: ['cpr', 'firstname', 'lastname'] Values: (('1111111115', 'Stine', 'Jacobsen '),)
Brug af OOogSQL 5 print aselection.makehtmltable() Resultat <table width="75%" border="1"> <tr> <td>cpr</td> <td>firstname</td> <td>lastname</td> </tr> <tr> <td>1111111115</td> <td>stine</td> <td>jacobsen </td> </tr> </table>
Fordelen ved UML Vi kan beskrive de logiske forhold i problemområdet uden at skulle tage beslutninger om implementeringen At kunne dette er jeres hovedkvalifikation. Har vi et godt UML diagram er der ikke lang vej til implementering for dygtige programmører. UML har en bestemt erkendelsesinterese: virkeligheden skal kunne repræsenteres algoritmisk.
Opgave 9..\øvelser\øvelse 9.doc