Python - Decorator

Python-Programming-Language

Decorator è uno dei Design Pattern strutturali trattati nella famosa raccolta della Gang of Four e permette all'utente di estendere le funzionalità di un oggetto esistente senza alterarne la struttura, fornendo un'alternativa flessibile alla definizione di sottoclassi ad hoc.
Ammetto candidamente che, durante gli anni di studi, il funzionamento di questo Design Pattern non mi era molto chiaro (probabilmente perchè mi era stato spiegato con un esempio sui panini che non avevo ben afferrato), ma dopo essermi messo a leggere svariati tutorial per Python sono arrivato finalmente ad apprezzare il costrutto. Questo perchè Python ci facilita abbastanza la vita in fase di implementazione.Come spiegato nelle guide trovate, a partire dalle quali sono riadattati gli esempi e delle quali potete trovare i link per approfondimenti in fondo alla pagina, dovete tenere a mente le caratteristiche di Python che andremo ad elencare di seguito:

Tutto è un oggetto

Come già introdotto nel primo articolo del sito sull'argomento Python, tutto quanto è un oggetto. Ribadiamo questo concetto perchè così come, dalla definizione del Design Pattern, un Decorator serve ad estendere a run-time le funzionalità di un oggetto, allo stesso modo in Python si possono utilizzare decoratori per estendere le funzionalità di singole funzioni o metodi... i quali sono considerati oggetti, per l'appunto.

Funzioni

Una funzione in Python è creata utilizzando la sintassi def nome_funzione(parametri):. Si possono definire funzioni all'interno di funzioni, le funzioni possono essere passate come parametro in ingresso ad altre funzioni e possono essere assegnate a variabili.

def main():
    print "sono nel main"

    # funzioni definite all'interno di una funzione
    def funzione_interna():
        return "sono nella funzione interna"
        
    def funzione_chiamante(f):
        print "sono nella funzione esterna"
        print f
    
    # assegnazione di una funzione ad una variabile
    fun = funzione_interna()
    
    # funzione passata come parametro in ingresso ad un'altra funzione
    funzione_chiamante(fun)
    
main()

Inoltre, le funzioni definite internamente hanno accesso alle variabili definite nella funzione esterna, come nel seguente esempio:

def funzione_esterna(param):
        
    def funzione_interna():        
        print "sono nella funzione interna"
        return "param funzione della esterna: " + param
        
    return funzione_interna

fun = funzione_esterna("pippo")
print fun()
# sono nella funzione interna
# param funzione della esterna: pippo

Decoriamo funzioni

Immaginiamo di avere una funzione che restituisce semplicemente un testo con una parte variabile a seconda del parametro d'ingresso. Se volessimo estendere questa semplice funzionalità per mostrare il testo in grassetto, potremmo costruire due funzioni come mostrato nel seguito:

def get_text(param):
   return "Benvenuto su {0}".format(param)

def bold_decorate(func):
   def wrapper(text):
       return "<b>{0}</b>".format(func(text))
   return wrapper

get_text_bold = bold_decorate(get_text)

print get_text_bold("allafinedelpalo.it")
# <b>Benvenuto su allafinedelpalo.it</b>

La funzione get_text() viene estesa tamite la funzione wrapper() del decoratore bold_decorate(). Il punto fondamentale è che get_text() è passato come parametro a bold_decorate() ed il risultato (la funzione estesa) è restituito nella variabile get_text_bold.

Una sintassi alternativa in Python utilizza @ per definire quale funzione è utilizzata come decoratore:

@bold_decorate
def get_text(param):
   return "Benvenuto su {0}".format(param)

def bold_decorate(func):
   def wrapper(text):
       return "<p>{0}</p>".format(func(text))
   return wrapper

print get_text("allafinedelpalo.it")

Una volta compresa la sintassi, potete riutilizzarla per aumentare le funzionalità delle classi e dei metodi che avete definito in passato.
Come sempre, vi invito a commentare se avete dubbi, precisazioni o aggiunte.

Fonti:

Alessio Antonielli

Ingegnere informatico, appassionato di cinema, musica, videogiochi e serie tv. Insomma, le solite cose che vi aspettereste da un ex studente di Ingegneria Informatica, giusto per rafforzare lo stereotipo…

Python - Decorator ultima modifica: 2016-04-27T11:34:36+00:00 da Alessio Antonielli


Advertisment ad adsense adlogger