-
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.