Post on 14-Nov-2015
description
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 1/12
CLASSIInquestalezionevedremocomesipossonointrodurrenuovitipiinPythontramiteilcostrutto class .L'utilitdiintrodurrenuovitipiillustratariscrivendoesempidiimageprocessingtramiteleclassi.
CLASSIPythoncomemoltialtrilinguaggiobjectorientedpermettediintrodurrenuovitipitramiteilconcettodiclasse.Unaclasseladefinizionediuntipoicuivalorisonooggettichehannounostatoechepossonoaveredelleoperazioni(metodi)chepossonoessereeseguitesudiessi.Adesempio,tuttiitipidiPython( int ,float , str ,ecc.)sonodefinititramiteclassietutteleoperazioniometodichepossonoessereeseguitisudiessisonodefinitinellaloroclasse.
L'usodelleclassinonnecessarioperrisolverenuoviproblemi.Matipicamenterendeilcodicepichiaroperchleclassipermettonoallostessotempodidefinireilsignificato(tipo)diunoggettoeleoperazioni(metodi)definitesuquesto,nascondendoinqualchecasoidettaglisucomequesteoperazionisonodefinite.Alcontrario,usaretipidibaseefunzioniportaadesseremoltopiesplicitiearicordarcipidettaglidurantelaprogrammazione(adesempiocheuncoloreunatupla (r,g,b) invecesemplicementediricordarcicheuncoloreunoggettoditipo Colore ).
Inizieremoconunesempiomoltosemplicediunaclasse Color cherappresentaungenericocolore.Specificheremocheuncolorehatrevariabili r , g e b ,chelorappresentanoehametodichesonooperazionidefinitesudiesso(come inverse ).Ognioggettoditipo Color rappresentauncolorespecifico,adesempioneroobianco,determinatoassegnandoopportunivalorialletrevariabili.
PerdefinireunaclasseinPythonlasintassilaseguente:
class NomeTipo(object): # object una parola chiave definizione dei metodi
Quindilaparolachiave class seguitadalnomechesivuoledarealnuovotipo(perconvenzionedovrebbeiniziareconunaletteramaiuscola)edopoi : eindentatiledefinizionideimetodideltipo NomeTipo .
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 2/12
ATTRIBUTIInPython,levariabilieimetodidefinitiinunaclassesonospessochiamatiattributi,nelsensochespecificanodeivaloriodelleoperazionichesono"attaccati"aglioggettidellaclasse.Ivaloridialcuniattributispessosonospecificatinelmomentoincuiunoggettodellaclassevienecreato.Perfarecic'unmetodospeciale,dettocostruttore,conilnome __init__ .Ilcostruttoreusatoperinizializzarelostatodell'oggettochestaperesserecreato.
class NomeTipo(object): def __init__(self, argomenti...): self.nome_variabile1 = valore1 ...
Vediamocomedefinirelaclasse Color conattributi r , g e b :
class Color(object): def __init__(self, r, g, b): self.r = r self.g = g self.b = b
Ilparametro self unparametrospecialechedevesempreessereilprimoparametrodiunmetododellaclasse.Pythonassegnaautomaticamentealparametro self l'oggettorelativamentealqualeilmetodostatochiamato,quindinondeveesserespecificatoquandosichiamaunmetodo.Nelcasodelcostruttoreilvaloredi self el'oggettochesistacostruendo.Lasintassidel . ,comegisappiamo,permettediaccedereaicosidettiattributidiunoggettochepossonoesseremetodiovariabili.Nelcasodi self.r , self.g eself.b sonovariabilichecontengonovalorinumerici.
OGGETTIPerusareunaclasse,creiamooggettidiqueltipo.Glioggettisicreanochiamandoilconstruttore,che,essendounmetodospeciale,sichiamaconunasintassias.Inquestocosachiameremoilnomedellaclasseconiparametrichevogliamopassarealcostruttore.
oggetto = NomeTipo(parametri...)
L'oggettoadessocreatosardeltipodellaclasseepotremmoaccedereallesuevariabiliutilizzandolanotazionedelpunto.
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 3/12
>>> c1 = Color(255,0,0)>>> type(c1)
>>> c1.r255>>> c1.g0>>> c1.b0
Secreiamodueoggettidellastessotipo,avremocheiltipolostesso,mailvalorememorizzatonellerispettivevariabilipuesserediverso.
>>> c2 = Color(0,255,0)>>> c2.r0>>> c2.g255>>> c2.b0
>>> type(c2)
>>> id(c1)4396694096>>> id(c2)4396694224
Seaccediamoavariabilinonesistenti,otteniamounerrore.
>>> c1.zTraceback (most recent call last): File "", line 1, in c1.z AttributeError: 'Color' object has no attribute 'z'
Ingenerale,glioggettiinPythonsonomutabili,ciopossiamodirettamenteaccedereallavariabiliemodificarle.Questomodificherilvalorediquellavariabilesoloperl'oggettochelacontiene,nonperglialtri.
>>> c1.g = 128>>> c1.g128>>> c2.g
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 4/12
255
Perchiarezza,visualizziamoilcomportamentonelvisualizzatore.
# definiamo la classeclass Color(object): def __init__(self,r,g,b): self.r = r self.g = g self.b = b
# creiamo un Color e impostiamolo a rossoc1 = Color(255,0,0)
# creiamo un altro Color e impostiamolo a verdec2 = Color(0,255,0)
# accediamo alle variabiliprint c1.r, c1.g, c1.bprint c2.r, c2.g, c2.b
# modifichiamo le variabilic1.r = 128print c1.r, c1.g, c1.bprint c2.r, c2.g, c2.b
METODIOltreadefinirevariabilipossiamoanchedefiniredelleoperazionisuoggetti.Questesonodettemetodieagiscono,ingenerale,sullevariabilidell'oggettosulqualesonochiamate.ConosciamogiimetodichePythondefinisceperitipibuiltincomestringheeliste,adesempio append e split .Perdefinireunmetodo,siseguelasintassideiconstruttori.Imetodiprendonosemprecomeprimoargomentol'oggettoself sucuiagiscono:
class NomeTipo(object): def nome_metodo(self, argomenti...): instruzioni...
Adesempio,possiamoaggiungereunmetodoallaclasse Color checreailcoloreinversoeloritorna:
class Color(object): def __init__(self, r, g, b):
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 5/12
self.r, self.g, self.b = r, g, b def inverse(self): return Color(255 - self.r, 255 - self.g, 255 - self.b)
Possiamochiamareunmetodousandolastessanotazionedelpunto,connomedelmetodoeargomenti.Comeperl'accessoallevariabili,unmetodopuesserechiamatosolamenteinrelazioneadunoggettoequindisolodopoavercreatounoggettodiqueltipo.
>>> c = Color(255,0,0)>>> c.r, c.g, c.b(255, 0, 0)>>> ci = c.inverse()>>> ci.r, ci.g, ci.b(0, 255, 255)
METODI SPECIALIAlcunimetodihannonomispecialicaratterizzatidalfattocheinizianoefinisconocondueunderscore __ .Questiservonoadefinireilcomportamentodeltiporelativamenteavarioperatori( + , in , str ,ecc.).Neabbiamogivistouno,ilconstruttorechepermettediinizializzareglioggettidiunaclasse.Cisonomoltialtrimetodispecialispecialmethodschepermettonodidarealleclassiscrittedall'utenteuncomportamentosimileaquellodeitipibuiltindiPython.Questomoltoutileperestendereillinguaggioeadattarloallarisoluzionedeiproblemipidiversi.Adesempio,perstampareoperoperaresuicolori,senzadefiniremetodispeciali,dobbiamoaccedereallevariabiliinmodoesplicito:
# definiamo due colori>>> c1 = Color(255,0,0)>>> c2 = Color(0,255,0)# proviamo a stamparli>>> print c1
>>> print c1.r, c1.g, c1.b255 0 0# proviamo a sommarli>>> c3 = c1 + c2Traceback (most recent call last): File "", line 1, in c3 = c1 + c2TypeError: unsupported operand type(s) for +: 'Color' and 'Color'# la somma non e' definita, abbiamo un errore
Sipunotarecomelavoraresuicolori,senzaladefinizionedimetodispeciali,poconaturalerispettoaitipi
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 6/12
builtindiPython.Nelnostroesempiopossiamodefiniredeimetodispecialiperstampareuncoloreinmodoleggibile,usando __str__ ,farelasommadiduecolori,usando __add__ emoltiplicareperunfattorecompresotra0.0e1.0,usando __mul__ :
class Color(object): def __init__(self, r, g, b): self.r, self.g, self.b = r, g, b def inverse(self): return Color(255 - self.r, 255 - self.g, 255 - self.b) def __str__(self): return 'Color('+str(self.r)+','+str(self.g)+','+str(self.b)+')' def __add__(self,other): return Color(self.r+other.r,self.g+other.g,self.b+other.b) def __mul__(self, f): return Color(self.r*f, self.g*f, self.b*f)
Lamoltiplicazioneperunfattoresipuusaresolamenteseilcolorel'operandodisinistra.
>>> c1 = Color(255,0,0)>>> print c1Color(255,0,0)>>> c2 = Color(0,255,0)>>> print c2Color(0,255,0)>>> c3 = c1 + c2>>> print c3Color(255,255,0)>>> c4 = c3*0.7>>> print c4Color(178.5,178.5,0.0)
INCAPSULAMENTOQuandousateinmodoadeguato,leclassipermettonodinascondereidettaglidicomeimetodisonoimplementati.Questoimportanteperchmiglioralaleggibilitdelcodice.Adesempio,perusarelist.append sufficientesaperecosafailmetodo,noncomelofa,ciononimportantesaperecomeilmetodoimplementato.InPythonsiusaunaconvenzionepernascondereidettagliimplementativi:tuttelevariabiliedimetodinascostiinizianocon _ .Perfareunesempiopicomplessodell'usodelleclassichedimostraanchequestoconcetto,creiamounaclasse Image checipermettedilavorarefacilmenteconleimmagini.Nelfarloreimplementeremoalcunefunzionigivistenellelezioniprecedenticomemetodidellaclasse.Percaricare,salvareevisualizzareun'immagine,continuiamoabasarcisulpacchetto image pernascondereidettaglidelformatoPNG.
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 7/12
Iniziamodefinendounaclasse Image cheadognipixelassociaunoggetto Color .Comeconstruttore,usiamol'equivalentedellafunzione image.create .Aggiungiamopoideimetodiperritornareledimensionidell'immagine,perleggereeimpostareisingolipixeldell'immagine,perleggereesalvarel'immaginesudisco,pervisualizzarlainIPythoneperstamparesempliciinformazionisudiessa.
import image
class Image(object): def __init__(self, w, h): self._pixels = [] for j in range(h): row = [] for i in range(w): row.append(Color(0,0,0)) self._pixels.append(row) def width(self): return len(self._pixels[0]) def height(self): return len(self._pixels) def set_pixel(self,i,j,color): if 0
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 8/12
Possiamooraaggiungeremetodipermodificareun'immagine,come copy e draw .Nelfarloutilizzermoimetodigidefinitinellaclasse.Notatecomeilcodicediventapileggibile(nonpitanti len e inside ),emoltomenopronoaderrori.
class Image(object): ... def draw_quad(self, x, y, w, h, c): for j in range(y, y+h): for i in range(x, x+w): self.set_pixel(i,j,c) def draw_gradienth(self, c0, c1): for j in range(self.height()): for i in range(self.width()): u = float(i) / float(self.width()) self.set_pixel(i,j,c0*(1-u)+c1*u) def draw_gradientv(self, c0, c1): for j in range(self.height()): for i in range(self.width()): v = float(j) / float(self.height()) self.set_pixel(i,j,c0*(1-v)+c1*v) def draw_gradientq(self, c00, c01, c10, c11): for j in range(self.height()): for i in range(self.width()): u = float(i) / float(self.width()) v = float(j) / float(self.height()) self.set_pixel(i,j,c00*(1-u)*(1-v)+ c01*(1-u)*v+c10*u*(1-v)+c11*u*v)
Inoltre,leoperazionidisommaemoltiplicazioneperunfattoredellaclasse Color permettonodiscrivereinmodomoltopisempliceimetodicheproduconoigradienti.
Possiamopoiinvocareivarimetodi:
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 9/12
img = Image(256,256)img.draw_quad(32,32,64,64,Color(255,128,0))img.draw_quad(160,160,64,64,Color(255,128,0))img.save('img_quad.png')
img = Image(256,256)img.draw_gradienth(Color(255,0,0),Color(0,255,0))img.save('img_gradh.png')
img = Image(256,256)img.draw_gradientv(Color(255,0,0),Color(0,255,0))img.save('img_gradv.png')
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 10/12
img = Image(256,256)img.draw_gradientq(Color(255,0,0),Color(0,255,0), Color(0,0,255),Color(0,0,0))img.save('img_gradq.png')
Inmododeltuttosimilesipossonoaggiungereanchetuttiifiltrivistiinprecedenza.
ESERCIZIScrivereiseguentimetodi.
1. Inversionedeicoloridell'interaimmagine,comedalezioneprecedente,usando Color.inverse .
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 11/12
2. Contrastodeicoloridell'interaimmagine,comedalezioneprecedente,usandoleoperazioniaritmetichesuicolori.Introdurreunmetodopercorreggereicolorifuoriscala.
3. Generaremosaici,comedalezioneprecedente,introducendounmetodopercalcolarelamediadeicoloriinunquadratinodell'immagine.
24/2/2015 FondamentidiProgrammazione
http://pellacini.di.uniroma1.it/teaching/fondamenti14/lectures/lecture12/notes.html 12/12
4. Introdurrelacopiadipartediun'immaginesuun'altra,comedalezioneprecedente.