1. Parte 2
Programmazione ad oggetti
in Python
Linguaggi dinamici – A.A. 2009/2010
1
2. Introduzione
„ Unità fondamentale degli oggetti: classe
„ Contenitore di variabili (attributi) e funzioni
(metodi)
„ Strumenti a di
St ti disposizione della OOP
i i d ll
„ Astrazione: capacità di ridurre il numero di
dettagli implementativi
d li i l i i
„ Incapsulamento: capacità di nascondere i
dettagli ai moduli esterni
„ Ereditarietà: capacità di perfezionare il
comportamento di una classe
„ Polimorfismo: capacità di adattare il
comportamento in funzione di ingressi e uscita
Linguaggi dinamici – A.A. 2009/2010
2
3. Definizione di classe in Python
„ Una classe è definita all'interno di un modulo,
tramite lo statement class
class ClassName:
<statement 1>
< t t t
…
<statement n>
„ Solitamente, gli statement sono definizioni di
funzioni (ma non è necessariamente detto)
„ La definizione di una classe crea un nuovo
namespace, che viene usato come lo scope della
classe (variabili locali)
Linguaggi dinamici – A.A. 2009/2010
3
4. Oggetti “classe”
„ Al termine della definizione di una classe,
l interprete
l'interprete crea un oggetto di tipo classe
„ Tale oggetto abilita due operazioni:
„ Attribute f
Att ib t reference: permette l'
tt l'accesso aglili
elementi di una classe (attributi e metodi),
tramite la sintassi NomeClasse nome elemento
NomeClasse.nome_elemento
„ Instantiation: permette la creazione di istanze di
classe (oggetti) tramite la notazione funzionale
variabile = NomeClasse()
„ L'istanziazione si preoccupa di invocare il
L'i t i i i i
metodo costruttore della classe
Linguaggi dinamici – A.A. 2009/2010
4
5. Creazione di un oggetto
„ Un oggetto viene creato “chiamando” la classe
„ o = MyClass()
„ Alla variabile o viene assegnato un riferimento
ad un oggetto di classe MyClass
„ Ricordarsi di importare il nome della classe se
è definito in un namespace diverso
„ Ad es., se MyClass è definita nel file
MyClass.py
M Cl
„ from MyClass import MyClass
namespace
p classe
Linguaggi dinamici – A.A. 2009/2010
5
6. ÆESEMPI
Il metodo costruttore
Bag.py
Complex.py
„ Il metodo costruttore di una classe ha il nome
__init__, e viene invocato automaticamente in
init
seguito all'istanziazione di una classe
„ Il metodo __init__, per il resto, gode di tutte le
init resto
proprietà delle funzioni
„ Argomenti con nome
A ti
„ Argomenti di default
„ C’è sempre un argomento implicito che
rappresenta l’oggetto
„ Lo stato interno di un oggetto è dichiarato
tramite opportune strutture dati
pp
Linguaggi dinamici – A.A. 2009/2010
6
7. ÆESEMPI
Attributi di dati
Complex2.py
„ Il Python permette la creazione automatica di
attributi all interno di un oggetto, tramite
all'interno oggetto
semplici operazioni di assegnazione
„ Ad esempio, posso creare un attributo counter
esempio
al volo su un oggetto x:
x.counter = 1
t
„ counter viene trattato alla stregua di una
variabile di appoggio, valida solo per l'istanza
x
„ Quando x viene distrutto, counter sparisce
„ counter può essere distrutto con del
p
Linguaggi dinamici – A.A. 2009/2010
7
8. Metodi
„ È possibile invocare i metodi di un oggetto o di
una classe con la notazione .
risultato = oggetto.metodo(argomenti)
„ Il primo argomento di ogni metodo, che viene
i t i t d h i
passato implicitamente dall'interprete, è
„ la reference all'oggetto istanza, se il metodo è
stato invocato tramite un'istanza
„ la reference all'oggetto classe, se il metodo è
stato invocato tramite la classe
„ Per convenzione, il primo argomento viene
nominato self
Linguaggi dinamici – A.A. 2009/2010
8
9. Metodi
„ Si noti che la chiamata
„ x = MyClass()
„ x.m()
„ corrisponde a:
i d
„ MyClass.m(x)
„ E in effetti il metodo è definito così:
„ class MyClass:
„ def m(self):
„ …
Linguaggi dinamici – A.A. 2009/2010
9
10. ÆESEMPI
Metodi
C.py
„ È anche possibile sfruttare funzioni definite
fuori dalla classe
„ Attraverso una variabile della classe che
rappresenta la funzione esterna
„ È valido anche per metodi definiti internamente
alla classe
Linguaggi dinamici – A.A. 2009/2010
10
11. Distruttori
„ In maniera simile al Perl, è previsto un
meccanismo di reference counting degli
oggetti
„ Si invoca la procedura di distruzione quando:
„ il reference count di un oggetto diventa nullo
„ si invoca il metodo del() sull'oggetto
ii d d l() ll'
„ Procedura di distruzione: l'interprete invoca il
metodo privato __del__() dell'oggetto (che sia
definito nell'oggetto stesso o ereditato da una
superclasse)
Linguaggi dinamici – A.A. 2009/2010
11
12. ÆESEMPI
Ereditarietà
Ereditarieta.py
„ Una classe può ereditare da un'altra classe
con la seguente sintassi:
class DerivedClassName(BaseClassName):
<statement 1>
< t t t
…
<statement n>
„ È possibile usare il nome completo della
p p
superclasse (comodo nelle situazioni in cui la
superclasse è definita in un altro file)
p )
„ Altrimenti ricordarsi di importare la classe dal
modulo
Linguaggi dinamici – A.A. 2009/2010
12
13. Ereditarietà multipla
„ Una classe può ereditare da più classi con la
seguente sintassi:
class DerivedClassName(C1, C2, C3):
<statement 1>
< t t t
…
<statement n>
„ È possibile usare il nome completo delle
p p
superclassi
„ La ricerca di un elemento non in C avviene per
profondità prima in C1 (e superclassi), poi in
C2 (e superclassi), e infine in C3 (e
superclassi)
Linguaggi dinamici – A.A. 2009/2010
13
14. Funzioni relative all’ereditarietà
„ Il Python definisce due funzioni nel contesto
dell ereditarietà
dell'ereditarietà
„ isinstance(obj, objtype): ritorna True se obj
è un'istanza della classe objtype
un istanza
„ issubclass(obj, objtype): ritorna True se obj
è una sottoclasse di objtype
tt l bjt
Linguaggi dinamici – A.A. 2009/2010
14
15. Polimorfismo
„ È sufficiente ridefinire un metodo all'interno di
una sottoclasse per sostituirlo alle definizioni
presenti nelle superclassi
„ L'interprete Python gestisce il polimorfismo
L interprete
automaticamente, andandosi a cercare il
metodo con la signature adatta
„ All'interno di un metodo ridefinito nella
sottoclasse, è possibile invocare il metodo
tt l ibil i t d
della superclasse con la seguente sintassi:
BaseClassName.methodname(self, arguments)
Linguaggi dinamici – A.A. 2009/2010
15
16. ÆESEMPI
Variabili private
Private.py
„ Ogni identificatore (variabile, metodo) __ident_
con almeno due underscore davanti ed al più
un underscore dietro viene rinominato
internamente in _c ass a e__ident, dove
te a e te classname de t, do e
classname è il nome della classe corrente
senza gli underscore iniziali
g
Linguaggi dinamici – A.A. 2009/2010
16
17. Vecchio e nuovo stile della POO
„ Nel vecchio stile:
„ Le classi sono oggetti
„ La ricerca di attributi avviene con un algoritmo
statico (depth-first left-to-right)
(depth-first,
„ Nel nuovo stile:
„ Le l
L classi sono ti i
i tipi
„ La ricerca di attributi avviene in modo dinamico
„ La gerarchia ha una radice: object
„ Il nuovo stile gestisce meglio casi di eredità “a
diamante”, in cui la stessa superclasse è
raggiungibile tramite percorsi diversi
Linguaggi dinamici – A.A. 2009/2010
17
18. ÆESEMPI
super
Counter.py
Counter2.py
„ In Python non c’è il concetto di super
„ Mancanza dovuta anche alla presenza di
ereditarietà multipla
„ Esiste però la funzione super(type object) che
super(type,
restituisce il “super tipo” della classe corrente
„ Funziona solo con il nuovo stile di classi
„ È necessario che all’apice della gerarchia ci
sia object
Linguaggi dinamici – A.A. 2009/2010
18
19. ÆESEMPI
Iteratori
Reverse.py
„ Il metodo __iter__ definisce un iteratore per la
classe corrente
„ Tale oggetto deve contenere un metodo
next()
„ Il metodo next definisce lo step di iterazione
„ Seleziona un elemento diverso ad ogni
invocazione
„ Solleva una eccezione di tipo StopIteration
quando tutti gli elementi sono stati selezionati
Linguaggi dinamici – A.A. 2009/2010
19