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.

Definizione classe

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().

Istanza di una classe

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.

Attributi di 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.

Attributi di classe

METODI DI ISTANZA

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.

Metodi di istanza

AGGIUNGERE ALTRI PARAMETRI DOPO SELF

Vediamo un esempio in cui passiamo un ulteriore parametro.

Metodi di istanza

ATTRIBUTI DI ISTANZA

Vengono creati sulle singole istanze della classe MyClass(). Vediamo un esempio:

Attributi di istanza
Attributi di istanza

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.

Costruttore

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 di classe

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.

Metodi statici
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.

LE CLASSI IN PYTHON LINK AL CODICE GITHUB

GITHUB

LA CLASSI IN PYTHON LINK AI POST PRECEDENTI

PREVIOUS POST LINKS