!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

Python
Objekter
Børre Stenseth
Python >Objekter

Objekter i Python

Hva
Litt om egne klasser og 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:

_landlister.py
Du kan teste dette her http://www.it.hiof.no/~borres/dw/pyobj/visland.html
Referanser
  1. Geonames GeoNames www.geonames.org/ 14-03-2010
  1. Python Objekter Python www.python.org/doc/newstyle/ 14-03-2010
Vedlikehold

B Stenseth, september 2007

( Velkommen ) Python >Objekter ( Databaser )