Funzioni

Una funzione è un frammento di codice associato a un nome che fa’ una serie di compiti e restituisce un valore. I frammenti di codice che hanno associato un nome e non restituisce valori sono spesso chiamati procedure. In Python non esistono procedure, perché quando il programmatore non specifica un valore di ritorno nella funzione restituisce il valore None (niente), equivalente a null in Java.
Oltre ad aiutare a programmare ed eseguire il debug dividendo il programma in parti, le funzioni consentono anche il riutilizzo del codice.
Dichiarazioni
In Python, le funzioni vengono dichiarati come segue:
		def mia_funzione(param1, param2):
		    print param1
		    print param2
Cioè, la parola chiave def seguita dal nome della funzione e gli argomenti tra parentesi tonde, separati da virgole. La definizione finisce con due punti e, in una nuova linea rientrata, possiamo scrivere il codice che compongono il blocco che deve essere eseguito dalla funzione.
Possiamo anche incontrare una stringa di testo nella prima riga del corpo funzione. Queste stringhe sono note con il nome di docstring (stringa di documentazione) e servono, come suggerisce il nome, per visualizzare la documentazione della funzione.
		def mia_funzione(param1, param2):
		    """Questa funzione consente di stampare i due valori 
		    passati come parametri"""
		    print param1
		    print param2
Questo è ciò che visualizza l’operatore ? di iPython o la funzione help del linguaggio per fornire assistenza sull’utilizzo e le utilità delle funzioni. Tutti gli oggetti possono avere docstring, non solo le funzioni, come vedremo di seguito.
Tornando alla dichiarazione di funzioni, è importante chiarire che dichiarando la funzione, tutto ciò che facciamo è quello di associare un nome al frammento di codice che costituisce la funzione, in modo da poterlo eseguire più tardi facendo riferimento al suo nome. Cioè, al momento della scrittura non si esegue la funzione. Per eseguire la funzione (l’esecuzione del codice) si dovrebbe scrivere:
		mia_funzione("Ciao", 2)
Cioè, il nome della funzione che vogliamo chiamare seguito dai valori che desideriamo passare come parametri tra parentesi tonde. L’associazione di parametri e valori passati alla funzione si fa’ normalmente da sinistra a destra: a param1 abbiamo assegnato il valore “ciao” e a param2 vale 2, mia_funzione stamperebbe ciao su una linea seguito dal 2.
Tuttavia è possibile modificare l’ordine dei parametri se indichiamo il nome del parametro da associare al valore, quando richiamamo la funzione:
		mia_funzione(param2 = 2, param1 = "Ciao")
Il numero di valori passati come parametri al richiamare la funzione deve corrispondere al numero di parametri che la funzione accetta secondo la dichiarazione della funzione. In caso contrario, Python si lamenterà:
		>>> mia_funzione("Ciao")
		Traceback (most recent call last):
		File "<stdin>", line 1, in <module>
		TypeError: mia_funzione() takes exactly 2 arguments (1 given)
È anche possibile, tuttavia, definire le funzioni con un numero variabile di argomenti, oppure è possibile assegnare valori predefiniti ai parametri nel caso non si indichi un valore per tale parametro, quando si chiama la funzione.
I valori di default per i parametri sono definiti ponendo un segno di uguale dopo il nome del parametro e quindi il valore di default:
		def stampare(testo, volte = 1):
		    print veces * texto
Nell’esempio precedente, se non indicano un valore per il secondo parametro verrà stampato una volta, la stringa passata come primo parametro:
		>>> stampare("Ciao")
		hola
… se si indica un altro valore, sarà questo il valore utilizzato:
		>>> stampare("Ciao", 2)
		CiaoCiao
Per definire funzioni con un numero variabile di argomenti dobbiamo scrivere un ultimo parametro nella dichiarazione della funzione il cui nome sarà preceduto dal segno *:
		def vari(param1, param2, *altri):
		    for val in altri:
		        print val
		vari(1, 2)
		vari(1, 2, 3)
		vari(1, 2, 3, 4)
Questa sintassi funziona creando una tupla (con il nome altri dell’esempio) che memorizza i valori di tutti i parametri aggiuntivi passati come argomento. Per la prima chiamata vari(1, 2), la tupla altri sarebbe vuota, dato che non sono stati passati altri parametri se non i due definiti per default, pertanto non stamperebbe niente. Nella seconda chiamata la tupla altri sarebbe (3), e nella terza (3, 4) che saranno stampati come da programma.
Si può anche precedere il nome del ultimo parametro con **, nel qual caso invece di una tupla si utilizzerebbe un dizionario. Le chiavi di questo dizionario sarebbero i nomi dei parametri specificati quando si chiama la funzione e i valori del dizionario sono i valori associati a questi parametri.
L’esempio seguente utilizza la funzione items dei dizionari, che restituisce una lista dei suoi elementi, per stampare i parametri contenuti nel dizionario.
		def vari(param1, param2, **altri):
		    for i in altri.items():
		        print i
		varios(1, 2, terzo = 3)
Chi conosce qualche altro linguaggio di programmazione si potrebbe chiedere se Python quando passa una variabile come argomento di una funzione lo fa’ per riferimento o per valore. Nel passaggio per riferimento ciò che viene passato come argomento è un riferimento o un puntatore alla variabile, vale a dire a un indirizzo di memoria in cui si trova il contenuto della variabile e non il suo contenuto. Nel passagio per valore, al contrario, ciò che viene passato come argomento è il valore che contiene la variabile.
La differenza tra entrambi è che nel passagio per valore le modifiche che si fanno sul parametro non si vedono al di fuori della funzione, dal momento che gli argomenti della funzione sono variabili locali alla funzione che contiene i valori indicati dalle variabili passate come argomento. In realtà ciò che viene passato alla funzione sono copie dei valori e non le variabili in sé.
Se volessimo modificare il valore di uno degli argomenti e che queste modifiche possano essere riflesse al di fuori della funzione dovremo passare il parametro per riferimento.
In C gli argomenti della funzione si passano per valore, anche se si può simulare il passaggio per riferimento usando puntatori. In Java si utilizza anche il passaggio per valore, sebbene per le variabili che sono oggetti ciò che viene passato per valore è il riferimento all’oggetto, e così sembra in realtà come un passaggio per riferimento.
Python utilizza anche il passaggio per valore di riferimenti agli oggetti, come in Java, anche se nel caso di Python, a differenza di Java, tutto è un oggetto (per l’esattezza quello che succede è che all’oggetto viene assegnato un’altra etichetta o il nome nello spazio dei nomi locale della funzione).
Tuttavia, non tutte le modifiche che facciamo ai parametri all’interno di una funzione Python si rifletteranno al di fuori di essa, giacché bisogna tener conto che ci sono oggetti immutabili in Python come le tuple, in modo che se proviamo a modificare una tupla passata come parametro ciò che accade, in realtà, è che si crea una nuova istanza, per cui le modifiche non si vedranno al di fuori della funzione.
Ecco un piccolo programma per dimostrarlo. Questo esempio utilizza il metodo append delle liste. Un metodo è semplicemente una funzione che appartiene a un oggetto, in questo caso a una lista. E append, in particolare, che serve per aggiungere un elemento a una lista.
		def f(x, y):
		    x = x + 3
		    y.append(23)
		    print x, y
		
		x = 22
		y = [22]
		f(x, y)
		print x, y
Il risultato dell’esecuzione di questo programma sarebbe
		25 [22, 23]
		22 [22, 23]
Come si vede la variabile x non conserva le modifiche una volta che lasciamo la funzione perché i numeri interi sono immutabili in Python. Tuttavia, la variabile y sì le conserva, perché le liste sono mutabili.
In breve: i valori mutevoli si comportano come passaggio per riferimento e gli immutabili come passaggio per valore.
Si conclude così tutte le questioni relative ai parametri delle funzione. Vediamo infine come restituire i valori, dove si utilizza la parola chiave return:
		def sommare(x, y):
		    return x + y
		print sommare(3, 2)
Come si vede questa semplice funzione non fa altro che sommare i valori passati come parametri e restituisce il risultato come valore di ritorno.
Possiamo passare anche più valori con return.
		def f(x, y):
		    return x * 2, y * 2
		a, b = f(1, 2)
Tuttavia, questo non significa che le funzioni di Python possono restituire più valori, ciò che accade è che Python crea una tupla al volo i cui elementi sono i valori da restituire, e questa è l’unica variabile che viene restituita.


Similari
Overloading di metodi in Java
12% Java
Un metodo overload viene utilizzato per riutilizzare il nome di un metodo ma con argomenti diversi, opzionalmente con un differente tipo di ritorno. [expand title=”Regole per overload” startwrap=”” endwrap=”” excerpt=”⤽” s…
Modi di fare e di non fare in Python
11% Python
Questo documento può essere considerato un compagno del tutorial di Python. Viene illustrato come utilizzare Python, e quasi ancora più importante, come non usare Python. [expand title=”Costrutti del linguaggio che non dov…
redirect 301 usando mod_alias
9% Server
mod_alias è fondamentalmente la versione più semplice di mod_rewrite. Non può fare le cose che fa mod_rewrite, ad esempio modificare la stringa di query. Per eseguire reindirizzamenti nel server web Apache è possibile di u…
Installare Python e Django su Windows
8% Django
Quando ci riferiamo allo sviluppo web con Python, la prima cosa che viene in mente è usare un qualche framework. Il più famoso e utilizzato da tutti è il Django, ma non è l’unico. Ci sono Pylons, Grok, TurboGears e Zope: t…
Metodi magici e costanti predefinite in PHP
8% Php
PHP fornisce un insieme di costanti predefinite e metodi magici per i nostri programmi. A differenza delle normali costanti i quali si impostano con define(), il valore delle costanti predefinite o speciali dipendono da do…