Python supporta diversi paradigmi per la programmazione compreso l’OOP (Object-Oriented Programming, programmazione orientata agli oggetti), un approccio il cui maggior vantaggio è quello di consentire la creazione di codice riutilizzabile. Tecnicamente l’OOP prevede di raggruppare sia le strutture dei dati e che le procedure che agiscono su di esse in una singola entità denominata classe.
Le classi
Una classe è in sostanza la rappresentazione astratta di qualcosa, ma istanziandola si possono generare degli oggetti caratterizzati da proprietà, i dati, e metodi, le procedure, che sull’oggetto operano. Un’istanza non è altro che l’oggetto di una classe, quindi si tratta di concetti che possono essere utilizzati come sinonimi.
Per definire una nuova classe in Python si utilizza la keyword class seguita dal nome della classe stessa a sua volta seguito dai due punti (":"). Per convenzione il nome della classe viene indicato con iniziale maiuscola.
# Definizione di una classe in Python
>>> class Gatto:
pass
Si noti l’utilizzo nell’esempio della keyword pass che indica un’operazione nulla, si tratta di una parola chiave utile quando viene richiesta un’istruzione ma non è necessario eseguire alcun codice. Nel caso specifico è stata impiegata per la definizione di una classe vuota, cioè ancora priva di istanze.
Gli oggetti
Come anticipato, un oggetto è l’istanza di una classe. E’ possibile considerare la classe "Gatto" definita in precedenza come la rappresentazione astratta di un gatto, mentre l’oggetto "gatto" sarà la sua rappresentazione concreta. Per capire meglio il concetto basterebbe pensare alla classe come alla descrizione di un gatto e all’oggetto "gatto" come ad un gatto vero e proprio, con gli attributi (età, colore..) e i comportamenti (miagolare, fare le fusa..) di questo felino.
Un semplice esempio di creazione di oggetti istanza di classe potrebbe essere il seguente:
# Definizione di classe e oggetto
class Gatto:
# attributo di classe
animale = "gatto"
# attributi istanze
def __init__(self, nome, colore):
self.nome = nome
self.colore = colore
# istanze della classe
tyson = Gatto("Tyson", "nero")
foreman = Gatto("Foreman", "bianco")
# accesso agli attributi di classe
print("Tyson è un {}".format(tyson.__class__.animale))
print("Anche Foreman è un {}".format(foreman.__class__.animale))
# accesso gli attributi dell'istanza
print("{} è di colore {}".format( tyson.nome, tyson.colore))
print("{} è invece di colore {}".format( foreman.nome, foreman.colore))
Una volta salvato il codice proposto in un file (chiamato ad esempio "gatto.py"), la sua esecuzione genererà un output come il seguente:
Tyson è un gatto Anche Foreman è un gatto Tyson è di colore nero Foreman è invece di colore bianco
Riassumendo brevemente le operazioni effettuate è possibile sottolineare i seguenti passaggi:
- viene definita la classe "Gatto" e i suoi attributi ("nome" e "colore"), cioè le caratteristiche dell’oggetto di classe;
- vengono generate le istanze di classe, "tyson" e "foreman" rappresentano quindi i valori (o referenze) degli oggetti;
- si accede agli attributi di classe tramite il costrutto *.__class__.animale, tali attributi sono i medesimi per tutte le istanze della classe.
- si accede agli attributi delle istanze (*.nome, *.colore)
- vengono generati degli output grazie all’accesso agli attributi delle istanze.
I metodi
I metodi di classe vengono utilizzati per definire i comportamenti dei suoi oggetti, si tratta in pratica di funzioni che vengono dichiarate all’interno del corpo di una classe. Un esempio di definizione dei metodi di classe potrebbe essere quello che segue:
# Definizione dei metodi di classe
class Max:
# istanza attributi
def __init__(self, nome):
self.nome = nome
# istanza metodo
def guida(self, auto):
return "{} guida una {}".format(self.nome, auto)
def destinazione(self, arrivo):
return "{} sta andando a {}".format(self.nome, arrivo)
# istanza oggetto
max = Max("Max")
# chiamata ai metodi
print(max.guida("Mercedes"))
print(max.destinazione("Milano"))
Mentre l’output generato dall’esecuzione del codice sarà:
Max guida una Mercedes Max sta andando a Milano
Quando si crea una nuova istanza di classe ("max = Max("Max")") è possibile accedere agli attributi di un oggetto tramite il suo nome (nel nostro caso "max"), tali attributi possono essere dei dati o anche dei metodi (ad esempio "max.guida()"). I metodi di un oggetto corrispondono a funzioni della classe di appartenenza e qualsiasi funzione che sia un attributo di classe definisce un metodo per gli oggetti della classe stessa.
Nel caso del nostro esempio abbiamo due metodi, "guida()" e "destinazione()". Si noti l’utilizzo in entrambi i casi del parametro self come primo argomento, ciò avviene perché il primo parametro richiesto è l’oggetto stesso.
"guida()" e "destinazione()" svolgono un compito molto semplice, quello di raccogliere dei dati e di utilizzarli per una stampa a video che avviene attraverso la chiamata ai metodi operata con la funzione print(). Il dato relativo al nome da stampare viene intercettato tramite __init__() che inizializza la variabile "nome", in Python essa viene definita "funzione speciale" e entra in gioco ogni volta che viene istanziato un nuovo oggetto di classe, per questo motivo prende il nome di costruttore.