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

  1. modificare la funzione circle_area() con un asserzione nella quale si verifica che il raggio è non negativo.

  2. modificare la funzione equation_solutions() aggiungendo l'asserzione mancante (da individuare)

  3. 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."
  4. 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: …")

results matching ""

    No results matching ""