CLASSI E ISTANZE
Gli oggetti classe forniscono in generale il comportamento di default, contengono una serie di attributi che poi sono dati e funzioni che nel contesto OOP vengono chiamati metodi. Le istanze vengono create, istanziate, a partire dalle classi e svolgono le attività all’interno dei programmi che noi scriviamo in Python.
LO STATEMENT CLASS
Lo statement class è uno statement composto che serve a definire e creare un oggetto classe assegnando un nome ad essa. Quando Python all’interno di un sorgente trova la keyword class, che ovviamente ha un header e una suite di istruzioni, lo esegue non creando le istanze della classe bensì l’oggetto classe. Vediamo come si dichiara una classe in Python.
class classname (base-classes):
statements
Le base-classes se ci sono vengono chiamate classi base o superclassi di classname che è la sottoclasse che stiamo definendo. Se ci sono più classi base queste devono essere separate da una virgola. Se non vengono indicate base-classes Python userà come classe base object. Vediamo come si definisce la più semplice delle classi in Python:
class MyClass:
pass
Lo statement pass non ha alcun effetto ma è uno statement valido consentendo di terminare la definizione della classe. Tale statement può essere usato anche nelle funzioni. Non avendo definito nulla dopo i due punti MyClass avrà come classe base object.
Il codice sopra riportato si legge affermando che non solo MyClass è una classe ma è anche istanza della classe type. Type è un tipo predefinito di Python che ha come istanze tutte le classi che andiamo a definire nei programmi. Vediamo ora come istanziare la classe che abbiamo appena definito. L’istanza creata erediterà tutti gli attributi di MyClass.
ISTANZIARE UNA CLASSE CODICE DI ESEMPIO
MyObj = MyClass()
Con questo assegnamento MyObj diventa istanza della classe MyClass().
ATTRIBUTI DI UNA CLASSE
Gli attributi possono essere di istanza o di classe. Gli attributi di classe vengono condivisi da tutte le istanze della classe.
MODIFICA DI UN ATTRIBUTO IN UN’ISTANZA
Se modifichiamo myAttr ad esempio nell’istanza m1 questo diventerà un attributo di istanza lasciando comunque inalterato l’attributo nella classe MyClass e nell’istanza m2.
METODI DI ISTANZA
myMethod diventa un attributo della classe e prende il nome di metodo. Anche i metodi sono condivisi fra tutte le istanze della classe. Tuttavia anche se condiviso il metodo definito in MyClass() deve poter riconoscere l’istanza che lo sta chiamando. Per questo motivo in Python i metodi hanno un primo parametro che per convenzione viene chiamato self e che rappresenta l’istanza che sta facendo la chiamata.
Quando le istanze m1 e m2 richiamano il metodo in realtà self non compare, questo perché quando invochiamo ad esempio da m1 MyMethod() Python dietro le quinte modifica l’invocazione chiamando il metodo sulla classe e passando l’oggetto m1 come primo parametro. Ovviamente se ci sono più argomenti verranno passati anche questi. Dal nostro punto di vista quello che si verifica è l’invocazione di myMethod() sull’istanza m1.
AGGIUNGERE ALTRI PARAMETRI DOPO SELF
Vediamo un esempio in cui passiamo un ulteriore parametro.
ATTRIBUTI DI ISTANZA
Vengono creati sulle singole istanze della classe MyClass(). Vediamo un esempio:
Se noi chiamiamo printMessage su una istanza su cui non è stato inizializzato l’attributo message otteniamo un errore. Questo è un comportamento scorretto. Vediamo come evitarlo.
IL COSTRUTTORE __INIT__
Il metodo __init__ viene sempre chiamato automaticamente appena costruiamo un’istanza della classe. Questo costruttore prende sempre come primo parametro self. In questo modo siamo sicuri che tutte le istanze di MyClass() saranno inizializzate con l’attributo message. Il metodo __init__ è in realtà un metodo di istanza, che prevede come primo parametro “self”, in quanto viene invocato sull’istanza non appena questa è stata creata dal runtime di Python.
METODI DI CLASSE
Sono metodi creati per essere eseguiti sull’oggetto classe e non sulle singole istanze. Questi metodi vengono chiamati direttamente dalla classe che viene passata come parametro cls all’interno del metodo. cls ha un significato analogo a self, la differenza è che self si riferisce ad una istanza di una classe mentre cls è la classe passata come parametro. I metodi di classe vengono marcati con un decoratore @classmethod. Generalmente questi metodi servono per istanziare una nuova istanza di classe, passando dei parametri diversi rispetto a quelli richiesti dal costruttore. Nell’esempio a fianco ogni volta che viene creata una istanza della classe viene chiamato il costruttore __init__ e incrementato il contatore.
METODI STATICI
A differenza di un metodo di classe un metodo statico non prende come primo parametro né un’istanza come self né il parametro di classe cls. È un metodo che può essere invocato direttamente sulla classe che serve a fornire un servizio e non si riferisce né alla classe né alle singole istanze.
class MyClass(object): counter=0 #servirà a contare quante istanze #vengono costruite sulla classe #counter in quanto definito nel body #della classe è un attributo di MyClass def __init__(self): MyClass.counter+=1 #Ogni volta che creiamo una #nuova istanza, viene chiamato #__init__ e incrementato il contatore @classmethod def istanze(cls): print(cls.counter) #Definiamo un metodo che non è applicabile alle #singole istanze ma alla classe stessa #il decoratore @classmethod serve a questo scopo. #cls per convenzione indica l'oggetto classe m1 = MyClass() m2 = MyClass() m3 = MyClass() MyClass.istanze() #stampa 3
class MyClass(): @staticmethod def somma(a,b): return a+b s=MyClass.somma(20,40) print(s)
APPROFONDIMENTO SULLE CLASSI
Le classi in Python sono un concetto fondamentale della programmazione orientata agli oggetti (OOP), un paradigma che organizza il codice attorno agli “oggetti”. Questi oggetti sono istanze di classi, che possono essere viste come dei blueprint (modelli) da cui si possono creare oggetti con proprietà e comportamenti definiti.
Cos’è una classe?
Una classe è una struttura che definisce un insieme di attributi (variabili) e metodi (funzioni) che caratterizzano gli oggetti che verranno creati da essa. Le classi servono per modellare concetti del mondo reale o logiche di applicazione in un programma.
Definire una classe
Per definire una classe in Python si usa la parola chiave class seguita dal nome della classe (che per convenzione inizia con una lettera maiuscola):
class NomeClasse:
pass # Placeholder, indica che la classe è vuota
Attributi di classe e di istanza
Gli attributi possono essere di classe o di istanza. Gli attributi di istanza sono legati a un oggetto specifico, mentre quelli di classe sono condivisi tra tutte le istanze della classe.
class Studente:
# Attributo di classe
scuola = “Scuola XYZ“
def __init__(self, nome, età):
# Attributi di istanza
self.nome = nome
self.età = età
Nell’esempio, scuola è un attributo di classe, mentre nome e età sono attributi di istanza.
Il metodo __init__
Il metodo __init__ è il costruttore di una classe in Python. Viene automaticamente chiamato quando si crea una nuova istanza della classe. Questo metodo inizializza gli attributi dell’oggetto.
class Studente:
def __init__(self, nome, età):
self.nome = nome
self.età = età
# Creazione di un’istanza della classe
studente1 = Studente(“Mario“, 20)
In questo esempio, quando creiamo studente1, Python chiama il metodo __init__ e assegna nome e età all’oggetto.
Metodi di istanza
I metodi sono funzioni definite all’interno di una classe che operano sugli attributi dell’istanza. Il primo parametro di ogni metodo è self, che rappresenta l’istanza stessa.
class Studente:
def __init__(self, nome, età):
self.nome = nome
self.età = età
def saluta(self):
return f”Ciao, sono {self.nome} e ho {self.età} anni.”
# Uso di un metodo
studente1 = Studente(“Mario“, 20)
print(studente1.saluta())
Ereditarietà
L’ereditarietà è un concetto che permette di creare una nuova classe basata su una classe esistente. La classe figlia eredita attributi e metodi della classe padre e può sovrascrivere o estenderli.
class Persona:
def __init__(self, nome, età):
self.nome = nome
self.età = età
def saluta(self):
return f”Ciao, sono {self.nome}.”
class Studente(Persona):
def __init__(self, nome, età, corso):
super().__init__(nome, età)
self.corso = corso
def saluta(self):
return f”Ciao, sono {self.nome} e studio {self.corso}.”
studente2 = Studente(“Anna“, 22, “Informatica“)
print(studente2.saluta())
In questo esempio, Studente eredita da Persona, ma ridefinisce il metodo saluta.
Incapsulamento
L’incapsulamento è la pratica di limitare l’accesso agli attributi e ai metodi di un oggetto, proteggendoli dall’accesso diretto dall’esterno. In Python, questo è realizzato con convenzioni di denominazione:
•_attributo: indicato per l’uso interno (privato, ma non strettamente)
•__attributo: la name mangling per evitare conflitti di nomi nelle classi derivate
class ContoBancario:
def __init__(self, saldo):
self.__saldo = saldo
def deposita(self, somma):
if somma > 0:
self.__saldo += somma
def mostra_saldo(self):
return self.__saldo
conto = ContoBancario(100)
conto.deposita(50)
print(conto.mostra_saldo()) # Output: 150
In questo esempio, __saldo è protetto dall’accesso diretto, consentendo il controllo su come viene modificato.
Lascia un commento