Alcune cose sulle funzioni
Introduzione
I commenti posti all'inizio della funzione hanno uno scopo di documentazione, ma anche, se ben predisposti, di semplice test del codice.
Sulla gestione delle eccezioni (blocco try… except) torneremo più avanti.
Nella funzione per il calcolo dell'area si noti l'uso delle asserzioni per la verifica dei parametri.
Nella funzione per le soluzioni di un'equazione di secondo grado, si noti che viene restituito None nel caso di assenza di soluzioni reali, oppure la coppia di soluzioni.
È anche utile sapere che:
- le funzioni, come in Pascal e a differenza del C, possono contenere al loro interno la definizione di altre funzioni (dette locali);
- i parametri delle funzioni possono avere un valore di default e un nome, in modo da poterli omettere (viene preso il valore di default) oppure essere passati in ordine diverso (con il loro nome).
Una semplice funzione per l'input controllato di numeri
def input_int(message):
"""Permette l'inserimento di un numero intero in maniera controllata.
Chiede in input una stringa usando *message* come prompt, poi
tenta la conversione in numero intero e restituisce il numero
convertito. Se viene inserito un valore che non è un numero,
viene richiesto di nuovo l'inserimento.
"""
while(True):
v=input(message)
try:
n=int(v)
return n
except ValueError as err:
print("Sembra che tu non abbia inserito un numero intero…")
k=input_int("Inserisci un numero: ")
print(k)
Una funzione migliore, che consente di inserire anche numeri in virgola mobile
def input_number(message, accept_float=False):
"""Permette l'inserimento di un numero in maniera controllata.
Chiede in input una stringa usando *message* come prompt, poi
tenta la conversione in numero e restituisce il numero
convertito. Se viene inserito un valore che non è un numero,
viene richiesto di nuovo l'inserimento.
Se *accept_float* è vero, accetta anche numeri in virgola mobile.
"""
while(True):
v=input(message)
try:
if accept_float:
n=float(v)
else:
n=int(v)
return n
except ValueError as err:
print("Sembra che tu non abbia inserito un numero valido…")
k=input_number("Inserisci un numero: ", True)
print(k, type(k))
Una funzione per il calcolo dell'area di un cerchio
import math
def circle_area(radius):
"""Restituisce l'area di un cerchio, dato il raggio *radius*.
>>> print(circle_area(12))
452.389342117
>>> print(circle_area(12.3))
475.291552562
"""
assert(isinstance(radius, (int, float)))
return radius ** 2 * math.pi
# Le istruzioni seguenti possono essere usate
# per eseguire i test messi nel commento
import doctest
doctest.testmod()
Una funzione per il calcolo delle soluzioni reali di un'equazione di secondo grado
def equation_solutions(a, b, c):
"""Restituisce una tupla con le soluzioni di un'equazione di secondo grado
I parametri *a*, *b* e *c* sono i coefficienti dell'equazione in forma
normalizzata (devono essere float).
La funzione restituisce None nel caso in cui l'equazione non ammetta
soluzioni.
>>> print(equation_solutions(1.0, 3.0, 2.0))
(-2.0, -1.0)
>>> print(equation_solutions(1.0, 1.0, 2.0))
None
"""
for p in a, b, c:
assert(isinstance(p, float))
d = b ** 2 - 4*a*c
if d<0:
return None
else:
d = math.sqrt(d)
return ((-b-d)/(2*a), (-b+d)/(2*a))
Alcune funzioni con parametri opzionali
def sayhello1(message):
"""Visualizza un messaggio di saluto (da indicare obbligatoriamente)
>>> sayhello1("hello, world!")
hello, world!
"""
print(message)
def sayhello2(message="ciao"):
"""Visualizza un messaggio di saluto (in assenza di indicazione, "ciao")
>>> sayhello2("hello, world!")
hello, world!
>>> sayhello2()
ciao
"""
print(message)
def sayhello3(message="ciao", times=2):
"""Visualizza un messaggio di saluto *times* volte
>>> sayhello3("ciao")
ciaociao
>>> sayhello3(message="ciao", times=3)
ciaociaociao
>>> sayhello3(times=1, message="ciao")
ciao
"""
print(message*times)
Argomenti annotati
È possibile aggiungere delle annotazioni per ciascuno degli argomenti di una funzione. L'annotazione non viene usata da Python, ma può essere utile a scopo di documentazione.
def rectangle_area(width: "the width, expressed in cm", height: "the height, expressed in cm"):
"""Restituisce l'area di un rettangolo, base per altezza
"""
return (width * height)
print(rectangle_area(5, 12))
help(rectangle_area)
L'output sarà il seguente:
60
Help on function rectangle_area in module __main__:
rectangle_area(width: 'the width, expressed in cm', height: 'the height, expressed in cm')
Restituisce l'area di un rettangolo, base per altezza
Funzioni senza argomenti
Naturalmente, è possibile definire funzioni senza argomenti:
def computeUltimateAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything()
return 42
# see http://tinyurl.com/ultimateanswer42
Nel richiamo, andranno messe le parentesi:
answer=computeUltimateAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything()
Valore restituito in mancanza di esplicitazione
Una funzione restituisce sempre un valore che, se non è indicato esplicitamente, è None. Questo valore di default restituito può essere comodo. Si pensi al seguente esempio di una funzione che deve restituire il rapporto tra due numeri, ma None nel caso in cui il secondo numero sia zero:
def Ratio(numerator, denominator):
if denominator!=0:
return numerator/denominator
else:
return None
print(Ratio(5,2))
print(Ratio(5,0))
2.5
None
La funzione avrebbe esattamente lo stesso comportamento se omettiamo di scrivere il ramo "else":
def Ratio(numerator, denominator):
if denominator!=0:
return numerator/denominator
Aiuto sulle funzioni predefinite
Tutte le funzioni predefinite di Python mettono a disposizione della documentazione sul loro uso direttamente nella shell di Python.
>>> help(ord)
Help on built-in function ord in module builtins:
ord(...)
ord(c) -> integer
Return the integer ordinal of a one-character string.
>>> help(math.sqrt)
Help on built-in function sqrt in module math:
sqrt(...)
sqrt(x)
Return the square root of x.
>>> s="python"
>>> help(s.upper)
Help on built-in function upper:
upper(...)
S.upper() -> str
Return a copy of S converted to uppercase.
Esercizi
modificare la funzione
circle_area()
con un asserzione nella quale si verifica che il raggio è non negativo.modificare la funzione
equation_solutions()
aggiungendo l'asserzione mancante (da individuare)scrivere un programma che:
- chieda in input il raggio di un cerchio in maniera controllata;
- calcoli l'area;
- visualizzi un messaggio del tipo "L'area di un cerchio di raggio X è Y."
scrivere un programma che:
- chieda all'utente i parametri a, b e c di un'equazione di secondo grado, accettandoli anche interi;
- chiami la funzione equation_solutions() per ottenere le soluzioni;
- visualizzi un messaggio con il risultato, in una forma tipo "L'equazione con parametri 1.0, 1.0, 2.0 non ha soluzione" (oppure "ha le seguenti soluzioni: …")