In Python ci sono tre tipi principali di metodi: metodi di istanza, metodi di classe e metodi statici. Storicamente, Python supportava solo metodi di istanza (con il primo parametro self). Col tempo, c'è stata la necessità di tipologie aggiuntive di metodi: accessibili tramite la classe senza legame a un oggetto e con accesso alla classe stessa.
Problema: spesso è necessario creare metodi che non dipendono dallo stato dell'istanza di un oggetto (ad esempio, metodi fabbrica) o che non necessitano di un contesto di classe, ma che logicamente appartengono alla struttura della classe.
Soluzione: vengono utilizzati i decoratori @classmethod e @staticmethod.
Esempio di codice:
class Example: def instance_method(self): return f'istanza: {self}' @classmethod def class_method(cls): return f'classe: {cls}' @staticmethod def static_method(): return 'statico'
Caratteristiche chiave:
Un metodo statico può accedere agli attributi della classe e dell'istanza?
No, il metodo statico non riceve un riferimento né alla classe né all'oggetto.
class A: x = 10 @staticmethod def f(): # print(self.x) # Errore pass
I metodi di classe possono essere sovrascritti nei discendenti?
Sì, chiamando classmethod tramite un discendente, il primo argomento sarà sempre la classe effettiva, non quella base.
class Base: @classmethod def name(cls): return cls.__name__ class Child(Base): pass Child.name() # "Child"
Perché non si può usare self per i metodi di classe?
Perché il metodo di classe non è legato a un oggetto specifico, ma alla classe nel suo complesso; self non è disponibile senza creare un'istanza.
Un metodo fabbrica è stato definito come staticmethod, ma al suo interno cerca di creare un'istanza della classe tramite self, il che porta a errori o duplicazione del codice.
Pro:
Contro:
La fabbrica è dichiarata tramite classmethod, all'interno si utilizza la classe effettiva (cls) per creare un'istanza. I discendenti vengono creati correttamente tramite questa fabbrica.
Pro:
Contro: