Introduzione alla OOP in Python

Questo articolo vuole introdurre ai pochi elementi fondamentali per utilizzare la OOP in Python per frammenti di codice prevalentemente pensati per i corsi di informatica di scuola superiore. Vi rimando a guide più articolate per conoscere dettagli in modo più specifico.

La OOP in Python

Python nasce come linguaggio di scripting, per sviluppi spesso semplici e con relativamente poche righe di codice da gestire. La mancanza di un programma main ne certifica ulteriormente questo scopo. Nel corso del tempo e della diffusione Python è sempre più utilizzato in progetti complessi ma a quel punto il paradigma semplicistico dello scripting comincia a a scricchiolare: occorre la programmazione orientata agli oggetti (OOP).

Le classi

Se abbiamo studiato un linguaggio OOP come Java e C#, alcune caratteristiche delle classi i Python ci potrebbero sconvolgere ma nell’ottica di semplificare, tutto appare più evidente. Alcune dinamiche possono essere reimplementate analogamente agli altri linguaggi ma occorre abbandonare lo standard aggiungendo altre librerie.

In python non si dichiarano in una sezione su misura gli attributi. Tutto viene fatto direttamente il quello che è di fatto il costruttore. Tale metodo non ha il solito nome della classe ma ha la dicitura __init__(self) per il costruttore standard, seguito da eventuali parametri per valorizzare inizialmente gli attributi in una istanza. Bada ben, ogni metodo associato d una classe come primo parametro ha sempre il self che equivale un po’ al this degli altri linguaggi Java/C++.

class Alunno:
    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome
    
    def stampa(self):
        print("Alunno: ", self.nome, " ", self.cognome)

if __name__ == "__main__":
    alfredo = Alunno("Alfredo", "Centinaro")
    alfredo.stampa()
    print(alfredo.nome) 

Come già si intuisce dal frammento di codice: pyhton non distingue attributi privati, pubblici o protetti. Tutti gli attributi sono pubblici violando il concetto di incapsulamento della OOP. Possiamo pur sempre andare a creare i metodi di accesso set/get ma anche a voler cercare qualcosa di simile abbiamo la possibilità di mettere due underscore davanti al nome self.__nome per indicare quell’attributo come offuscato, da non gestire direttamente ma pur sempre visibile come alfredo._Alfredo__nome quindi più complesso da scrivere ma senza reale vantaggio. In pratica il programmatore che sceglie questa modalità da semplicemente un avvertimento nell’accesso diretto.

Metodi

Come intuibile, i metodi sono delle banali funzioni ma con il parametro self iniziale obbligatorio. Le funzioni sono tutte pubbliche. L’unica accortezza è magari di utilizzare le annotazioni (leggi qui) per rendere il codice commentato e meglio leggibile. Vediamo una manciata di esempi per completezza:

def stampa(self):
    print("Alunno: ", self.nome, " ", self.cognome)

def getNome(self):
    return self._name

def setNome(self, _nome):
    if isinstance(_nome, str):
       self.nome = _nome
   else:
       return

def setPrelievo(self, _denaro):
    if self.conto > _denaro:
        self.conto -= _denaro
    else:
        return

Overloading dei metodi

L’overloading non è possibile in modo esplicito in Python, altra stranezza contro il mondo OOP. E’ possibile fare overloading solo del costruttore __init__. Nel codice sopra, se volessi un metodo stampa(self) ed uno stampa(self, _saluto) non posso realizzarlo esplicitamente. Possiamo provare a mettere parametri inizializzati a None o usare un trucco con la libreria from typing import overload ma nulla ci consente un vero overloading. Bisognerà esplicitamente creare metodi separati o passare eventualmente un vettore/lista di parametri da validare ed utilizzare rendendo il codice più complesso.

class Alunno:
    def __init__(self):
        self.nome = ""
        self.cognome = ""

    def __init__(self,  _cognome):
        self.nome = ""
        self.cognome = _cognome

    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome

Ultima modifica 11 Novembre 2025