Objekter i Python
Moduler og klasser
Python opererer med moduler og objekter.
Moduler
Modulbegrepet er trolig inspirert av Pascal eller Modula. Vi vet at vi kan lage moduler med funksjoner og aksessere disse funksjonene ved hjelp av dot-notasjon. F.eks. slik:
import math print math.sqrt(25)
Vi importerer modulen math og bruker funksjonen sqrt() som er definert i math. math er ikke en klasse, men en modul. I dette tilfellet brukte vi en standardmodul, men vi vet at vi kan lage våre egne moduler. Vi vet videre at vi kan aksessere, ikke bare funksjoner, men også globale variable i moduler. F.eks. slik:
import math print math.sin(math.pi/2.0)
Det greieste er vel å betrakte moduler som en måte å ordne biblioteker på, selv om det i programkoden kan se ut som vi opererer mot objekter. Av og til har vi klasser i moduler. F.eks:
import datetime now=datetime.date.today() print now.year mydate=datetime.date(1946,12,27) print mydate.day
Vi bruker klassen date i modulen datetime. Vi bruker først den statiske funksjonen today() for å konstruere et date-objekt. Deretter lager vi et date-bjekt ved hjelp av en konstuktor som tar år, mnd, dag som input.
Klasser
Python er et objektorientert språk. Vi kan betrakte datatyper og innebygde datastrukturer som objekter.
Klasse begrepet i Python har endret seg. I Pythondokumentasjonen (language reference 3.3) uttrykkes dette slik: "Classes and instances come in two flavors: old-style or classic, and new-style."
Nedenfor skal vi se på noen svært enkle eksempler på egne klasser. Vi skal uttrykke oss i "new-style", men ikke gå spesielt dypt i materien. innføringen er basert på noen enkle eksempler.
Eksempel 1
I det første eksempelet lager vi en klasse for å beskrive personobjekter, og vi lager en person. Vi lager personklassen som en klasse som arver fra object. objekt er "alle klassers mor" i det nye klassebegrepet i Python. object har, i Python som i andre språk med tilsvarende kosntruksjon, noen grunnleggende metoder som er nyttig i en del sammenhenger. Vi forfølger ikke dette i det første eksempelet.
class person(object): def __init__(self,n,a): self.name=n self.address=a ole=person('ole','Halden') print ole.name
Merk at __init__ fungerer som en konstruktor. Merk videre bruken av self. Siden Python ikke har noen mekanismer for å deklarere variable, brukes f.eks. self.address for å definere en lokal variabel address, "dette objektets address". self må alltid være i den formelle parameterlista i klassemetoder. Vi kan skrive om personklassen slik at den ligner på den formen vi vanligvis bruker i Javabeans.
class person(object): def __init__(self,n,a): self.name=n self.address=a def getName(self): return self.name def getAddress(self): return self.address def setName(self,n): self.name=n def setAddress(self,a): self.address=a def __str__(self): return self.name+' fra '+self.address ole=person('ole','Halden') print ole.__str__() print ole.getName() ole.setName('Ole Jakob') print ole.__str__() print ole.getName()
med resultat:
ole fra Halden ole Ole Jakob fra Halden Ole Jakob
Merk at __str__(self) er en redefinisjon av tilsvarende funksjon i object.
Eksempel 2
Nå bygger vi ut personklassen, og definerer en subklasse: ansatt'.
class person(object): def __init__(self,n,a): self.name=n self.address=a def getName(self): return self.name def getAddress(self): return self.address def setName(self,n): self.name=n def setAddress(self,a): self.address=a def __str__(self): return self.name+' fra '+self.address class ansatt(person): def __init__(self,n,a,j): person.__init__(self,n,a) self.job=j def getJob(self): return self.job def setJob(self,j): self.job=j def __str__(self): return person.__str__(self)+' har jobb som '+self.job hans=ansatt('hans','Halden','vaktmester') print hans.__str__() hans.setName('Hans Jakob') hans.setJob('regnskapssjef') print hans.__str__() print super(ansatt,hans).__str__()
med utskriften:
hans fra Halden har jobb som vaktmester Hans Jakob fra Halden har jobb som regnskapssjef Hans Jakob fra Halden
Eksempel 3
Et litt mer praktisk eksempel: Vi leser data fra en kommaseparert fil og bygger opp en liste av objekter, ett for hver linje. Som datagrunnlag bruker vi landbeskrivelser fra geonames [1] . Datasettet er beskrevet i modulen Noen datasett , og dataene er slik: land.txt
import urllib """ Using a class to administrate geodata """ #--------------------------------- # a class to hold : countryname,continent,area, capital class country(object): def __init__(self,plist): self.countryName=plist[4] self.continent=plist[8] self.capital=plist[5] if plist[6]=='': self.area=0.0 else: self.area=float(plist[6]) def __str__(self): return self.countryName def printAllOfMe(self): return str(self.area)+'\t'+self.countryName+' - '+self.capital #------------------------------- # continets [isocode,fullname] continents=[['EU','Europa'],['AS','Asia'],['NA', 'North America'], ['AN','Antarctica'],['SA','South America'],['OC','Oceania'], ['','No region']] # --------------------------------- # read from whereever you place the data # pick a country from each line and produce an object list def makeCountryList(): try: allCountries=[] # quick and dirty: surl='http://www.ia.hiof.no/~borres/commondata/geonames/land.txt' T=urllib.urlopen(surl).read() lines=T.split('\n') for line in lines: parts=line.split('\t') if len(parts)!=12 or line.startswith('iso'): continue allCountries.append(country(parts)) return allCountries except: return[] #------------------- # report a list pr continent def reportContinent(countryList): result='' for c in continents: result+=c[1]+'\n' for cobj in countryList: if cobj.continent==c[0]: result+='\t'+cobj.__str__()+'\n' return result #------------------ # report all countries sorted on area # sort helper def compareCountries(c1,c2): if c1.area < c2.area: return 1 if c2.area < c1.area: return -1 return 0 def reportOnSize(countryList): result='' countryList.sort(compareCountries) for cobj in countryList: result+=cobj.printAllOfMe()+'\n' return result #--------------------------- # testing the module if __name__=="__main__": clist=makeCountryList() print reportOnSize(clist) print reportContinent(clist)
Det er en enkel sak å skrive om rapporteringen slik at vi får ut f.eks. et HTML-format. Hvis vi gjør dette og preparerer koden som et CGI-skript, få vi følgende: