Python
Objekter
Python
Børre Stenseth

Objekter i Python

Hva

Vi har brukt modulbegrepet i andre deler av dette materialet. En modul er ikke en klasse. 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. 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.

Klasser og objekter

Python er et objektorientert språk. Vi kan betrakte datatyper og innebygde datastrukturer som objekter.

Nedenfor skal vi se på noen svært enkle eksempler på egne klasser. 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 konstruksjon, 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 f.eks. Java.

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 website: Data , og dataene er slik: https://borres.hiof.no/wep/data/geografi/land.txt

from urllib import request
"""
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='https://borres.hiof.no/wep/data/geografi/land.txt'
        f=request.urlopen(surl)
        T=f.read().decode() #since read returns bytes
        f.close()
        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:
        print('error')
        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 sortKey(c):
    return c.area
    
def reportOnSize(countryList):
    result=''
    countryList.sort(key=sortKey)
    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:

_landlister.py
Referanser
  1. Geonames GeoNames www.geonames.org/ 14-03-2010