Tecnologie dell'Informazione e della Comunicazionegaspari/www/teaching/tic8.pdf · © Mauro Gaspari...
Transcript of Tecnologie dell'Informazione e della Comunicazionegaspari/www/teaching/tic8.pdf · © Mauro Gaspari...
© Mauro Gaspari - University of Bologna - [email protected]
Tecnologie dell'Informazione e della Comunicazione
Capitolo 11Classi e Oggetti
Prof. Mauro Gaspari: [email protected]
© Mauro Gaspari - University of Bologna - [email protected]
Definire nuovi tipi?
● Abbiamo visto diversi tipi di dato strutturati:– stringhe
– liste
– tuple
– dizionari
● È possibile definirne dei nuovi, che magari siano specifici per particolari applicazioni?
© Mauro Gaspari - University of Bologna - [email protected]
Tipi di dato Astratti● Che caratteristiche hanno i tipi di dato visti fino ad ora:
– contengono informazioni (scalari/strutturate)
– ci sono un insieme di operazioni predefinite che sono le uniche che accedono all'implementazione del dato.
– l'utente non è a conoscenza di come sono realizzate internamente queste operazioni (sono incapsulate).
● Le operazioni si possono utilizzare con una certa tranquillità,
senza conoscere i dettagli di come sono realizzate (information
hiding).
● Un tipo di dato che ha queste proprietà si chiama tipo di dato
astratto (=abstract data type).
© Mauro Gaspari - University of Bologna - [email protected]
Tipi di dato definiti dall'utente
● Buoni tipi di dato definiti dall'utente dovrebbero avere le caratteristiche dei tipi di dato astratti.
● Ovvero:– implementazione nascosta.
– un insieme di procedure e funzioni che accedono al dato che sono le uniche che accedono al dato.
© Mauro Gaspari - University of Bologna - [email protected]
Un esempio: il punto
● Concetto di punto in matematica.
● In uno spazio bidimensionale un punto è rappresentato da due
numeri, le coordinate, che vengono trattate insieme come un
singolo oggetto.
● Esempio di notazione matematica:
– (0,0) origine
– (x,y) rappresenta un punto con coordinate x e y.
© Mauro Gaspari - University of Bologna - [email protected]
Come realizzare un punto in Python?
● Si potrebbe rappresentare con due numeri floating-point.
● Sarebbe però opportuno raggrupparli in un singolo oggetto.
– lista
– tupla
● Una soluzione può essere meglio dell'altra a seconda
dell'applicazione. Ad esempio se si vuole trovare dei punti che
possono essere modificati è meglio utilizzare le liste.
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
● Realizzazione di un punto come lista.
● Definizione della funzione muovi, che sposta il punto.
>>> punto = [0,0]>>> def muovi(p,x,y)... p[0] = x... p[1] = y...>>> muovi(punto,4,5)>>> punto[4,5]
© Mauro Gaspari - University of Bologna - [email protected]
Osservazioni● Una volta scelta la rappresentazione si realizzano le operazioni
che operano sui punti, ad esempio la funzione muovi.
● Però il punto così definito non è un tipo di dato astratto, ovvero
non:
– Posso usare altre funzioni sul punto, ad esempio len.
– È facile definire altre operazioni che accedono alla struttura interna del punto.
– Posso addirittura modificare la struttura senza rendermene conto.
– Il tipo (type) non risulta essere punto ma lista.
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
>>> len(punto)2>>> type(punto)<type 'list'>>>> punto[1:1] = [5,6]>>> punto[4, 5, 6, 5]>>>
© Mauro Gaspari - University of Bologna - [email protected]
Le classi
● Python, come altri linguaggi di programmazione, fornisce dei
meccanismi ad alto livello per creare tipi di dato definiti
dall'utente che siano più vicini ai tipi predefiniti.
● Questi tipi si definiscono con il concetto di classe (= class).
class Point: def __init__(self, x, y): self.x = x self.y = y
© Mauro Gaspari - University of Bologna - [email protected]
Le classi● Queste definizioni possono apparire in qualsiasi punto del
programma ma di solito è opportuno inserirle all'inizio dopo i
comandi import.
● Le regole sintattiche per definire le classi sono simili a quelle
degli altri tipi composti.
● La definizione crea una nuova classe. Quando si crea una classe
Point si crea anche un nuovo tipo chiamato Point.
● I membri di questa classe sono detti istanze del tipo creato oppure
oggetti.
© Mauro Gaspari - University of Bologna - [email protected]
La funzione __init__: un metodo.
● La funzione __init__ definisce come inizializzare i membri della
classe, si chiama anche metodo (= method) perché può essere
invocata solo sugli elementi della classe.
– la variabile self si riferisce all'oggetto che sto creando, per convenzione deve essere il primo argomento del metodo;
– la classe Point a due attributi x e y;
– le notazioni self.x e self.y indica gli attributi dell'oggetto (la notazione è simile a quella dei moduli).
© Mauro Gaspari - University of Bologna - [email protected]
Istanze o Oggetti
● Per creare le istanze della classe Point si usa una funzione
costruttore denominata Point, che invoca in modo trasparente la
funzione __init__
blank = Point(0,0)
Alla variabile blank vieneassegnato un riferimentoal nuovo oggetto.
© Mauro Gaspari - University of Bologna - [email protected]
Osservazioni
● La creazione di un oggetto si dice istanziazione.
● La funzione __init__ potrebbe non esserci. In tal caso si creano
oggetti senza attributi. Questi potrebbero essere aggiunti in
seguito.
● Per rendere più chiara la struttura dei programmi che contengono
nuovi tipi. Si consigli di utilizzare sempre la funzione __init__ e
di inserire tutti gli attributi di una classe in questa funzione.
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
>>> blank.x0>>> blank.y0>>> blank<__main__.Point instance at 0xb7f75c2c>>>>>>> type(blank)<type 'instance'>>>>
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
● Posso modificare gli attributi di un oggetto:
>>> blank.x = 3.0>>> blank.y = 4.0
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
>>> print blank.y4.0>>> x = blank.x>>> print x3.0
La notazione con il punto si usa anche per accedereagli attributi.
NB. non c'è conflitto tra lax variabile e quella nell'oggettoche è un attributo.
© Mauro Gaspari - University of Bologna - [email protected]
Stampare un oggetto
>>> blank<__main__.Point instance at 0xb7f75c2c>
# si stampa il riferimento in esadecimale
def printPoint(p): print '(' + str(p.x) + ', ' + str(p.y) + ')'
NB. un oggetto può essere passato come parametro.Come nel caso delle liste si passa il riferimento.
© Mauro Gaspari - University of Bologna - [email protected]
Valori di default
● Alle funzioni è possibile dare valori di default.
● Lo stesso si può fare con i metodi.
def stampaSempre(x=0):... print x...>>> stampaSempre(1)1>>> stampaSempre()0
© Mauro Gaspari - University of Bologna - [email protected]
Esempi
def find(str, ch):
index = 0
while index < len(str):
if str[index] == ch:
return index
index = index + 1
return 1def find(str, ch, start=0):
index = start
while index < len(str):
if str[index] == ch:
return index
index = index + 1
return 1
© Mauro Gaspari - University of Bologna - [email protected]
Una definizione migliore di Punto
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return '(' + str(self.x) + ', ' + str(self.y) + ')'
def muovi(self,a,b):
self.x = a
self.y = b
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
>>> p = Point(3, 4)>>> str(p)'(3, 4)'
>>> p = Point(3, 4)>>> print p(3, 4)
NB: __str__ overrides il comportamento standard di str
La print su un oggetto chiama str.
© Mauro Gaspari - University of Bologna - [email protected]
Uno script con la classe Pointclass Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return '(' + str(self.x) + ', ' + str(self.y) + ')'
def muovi(self,a,b):
self.x = a
self.y = b
b = Point(4,5)
b.muovi(6,7)
print(b)
NB. Gli oggetti sono mutabili!
© Mauro Gaspari - University of Bologna - [email protected]
Quando due oggetti sono uguali?
● Si è già discusso in precedenza del concetto di uguaglianza tra
elementi in Python.
● In genere il concetto di uguaglianza può essere definito in modi
diversi.
● Ad esempio “Abbiamo la stessa macchina” non significa di solito
che la macchina in questione sia lo stesso oggetto, ma piuttosto
che la marca e il modello sono gli stessi.
● Se si dice invece “Abbiamo la stessa Mamma” allora si tratta ella
stessa persona.
© Mauro Gaspari - University of Bologna - [email protected]
Quindi?
● L'idea di uguaglianza dipende dal contesto.
● Anche con gli oggetti nei linguaggi di programmazione c'è lo stesso tipo di ambiguità.
● Per esempio se si dice che due punti sono uguali:– Contengono le stesse coordinate?
– Sono lo stesso oggetto (stesso id).
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
>>> p1 = Point(3,4)>>> p2 = Point(3,4)>>> p1 == p20>>> p2 = p1>>> p1 == p21
© Mauro Gaspari - University of Bologna - [email protected]
Tipi di equivalenza
● L'equivalenza su gli oggetti si dice anche equivalenza superficiale (= shallow equality) perchè confronta solo i riferimenti agli oggetti e non il contenuto.
● L'equivalenza che si basa invece sul contenuto degli oggetti si definisce equivalenza profonda (=deep equality).
© Mauro Gaspari - University of Bologna - [email protected]
Esempio
● Definizione di una deep equality sui punti.
samePoint(p1, p2) : return (p1.x == p2.x) and (p1.y == p2.y)
© Mauro Gaspari - University of Bologna - [email protected]
Programmazione basata su oggetti
● La programmazione vista fino ad ora si chiama basata su oggetti (=object based).
● Un programma è costituito da un insieme di definizioni di classi e di operazioni sugli oggetti di queste classi.
● Cosa vuol dire allora orientato agli oggetti (=object oriented)?
© Mauro Gaspari - University of Bologna - [email protected]
Un oggetto rettangolo
class Rectangle:def __init__(self,width,height,x,y):
self.corner = Point(x,y) self.width = width self.height = height
box = Rectangle(100.0,200.0,0.0,0.0)
NB. in questo modo abbiamo inclusoun oggetto dentro un altro.
© Mauro Gaspari - University of Bologna - [email protected]
Oggetti composti
Gli oggetti composti si accedono concatenandodiversi operatori punto:
>>> print box.corner.x
© Mauro Gaspari - University of Bologna - [email protected]
Esempio istanze come valori restituiti
def findCenter(box): p = Point() p.x = box.corner.x + box.width/2.0 p.y = box.corner.y + box.height/2.0 return p
>>> center = findCenter(box)>>> printPoint(center)(50.0, 100.0)
© Mauro Gaspari - University of Bologna - [email protected]
Copiare oggetti
● Anche gli oggetti come le liste hanno il problema dell'aliasing.
● Spesso conviene copiare oggetti per evitare il rischio di modifiche
indesiderate.
● Python fornisce il modulo copy proprio per questo.
>>> import copy>>> p1 = Point(3,4)>>> p2 = copy.copy(p1)>>> p1 == p20>>> samePoint(p1, p2)1
© Mauro Gaspari - University of Bologna - [email protected]
Osservazioni
● Attenzione la funzione copy.copy (ovvero la funzione copy nel modulo copy) realizza uno shallow copyng.
© Mauro Gaspari - University of Bologna - [email protected]
Esempi
def growRect(box, dwidth, dheight) : box.width = box.width + dwidth box.height = box.height + dheight
Per esercizio fare una funzione moveRect che sposta il rettangolo.
© Mauro Gaspari - University of Bologna - [email protected]
Osservazioni
● Se uso shallow copy ma growRect funziona bene mentre la moveRect sposterebbe entrambi i triangoli.
● Fortunatamente il modulo copy fornisce una funzione deepcopy che copia completamente un oggetto deferenziando (seguendo) i riferimenti che trova.
© Mauro Gaspari - University of Bologna - [email protected]
Esempi
>>> b2 = copy.deepcopy(b1)
# a questo punto b1 e b2 sono oggetti# completamente separati
def growRect(box, dwidth, dheight) : import copy newBox = copy.deepcopy(box) newBox.width = newBox.width + dwidth newBox.height = newBox.height + dheight return newBox