Sei sulla pagina 1di 23

Funzioni

Introduzione

http://plm.dia.uniroma3.it/milicchio/
milicchio@dia.uniroma3.it
@fmilicchio

Panoramica
Con i concetti fino ad ora introdotti possibile risolvere problemi
arbitrariamente complessi

Per la programmazione macchinosa e complessa

dicile correggere il codice se di grosse dimensioni

Un esempio cardine rappresentato da porzioni di codice ripetuto

Per tale scopo, conveniente (leggi fondamentale) partizionare il codice

Le funzioni sono una possibile modalit di risolvere il problema della


complessit di un programma

Esempio
Radici delle equazioni di II grado

Specifica:

Date due equazioni di secondo grado della forma a x2 + b x + c = 0

Calcolare le eventuali radici reali e verificare se le due equazioni hanno


radici reali comuni

Si tratta di un problema estremamente semplice, risolvibile anche senza


sottoprogrammi ed utilizzato a scopo didattico

Essendo semplice, facilmente controllabile

Progetto di Riferimento
import math

Input/Output

print "Prima equazione"


a1 = float(raw_input("a = "))
b1 = float(raw_input("b = "))
c1 = float(raw_input("c = "))

print "Seconda equazione"


a2 = float(raw_input("a = "))
b2 = float(raw_input("b = "))
c2 = float(raw_input("c = "))

print "Eq.", a1, "x^2 + ", b1, "x + ", c1


print "Eq.", a2, "x^2 + ", b2, "x + ", c2

d1 = b1**2 - 4.0 * a1 * c1
d2 = b2**2 - 4.0 * a2 * c2
print d1, d2

Discriminante

Difetti
Il codice spesso ripetuto (e.g., input/output, discriminante)

Se dovessi passare da 2 a 3, o 4 equazioni, sarebbe necessario moltiplicare il


codice e modificarlo opportunamente

Questo aumenta notevolmente la probabilit di commettere errori

Inoltre, rende il programma dicile da verificare e manutenere

Se ci sono errori, devono essere corretti in punti diversi del programma

Possibile Soluzione
Idealmente vorrei scrivere una volta sola il codice per le varie operazioni da
ripetere

Vorrei quindi poterlo eseguire di volta in volta su argomenti diversi (e.g.,


equazioni diverse)

Esempio: il calcolo del discriminante calcolato come se ci fosse una funzione


predefinita apposita

Ulteriore esempio: la lettura dei coecienti di una equazione

Python fornisce, come tanti linguaggi di programmazione, la possibilit di


creare funzioni (talvolta chiamati col nome desueto di sottoprogrammi)

Funzioni
bene identificare le funzioni con le funzioni matematiche

Una funzione ha un dominio, ed un codominio

Come in matematica, per utilizzare una funzione f, prima tale funzione deve
essere definita

Abbiamo implicitamente utilizzato molte funzioni, come ad esmpio


math.sqrt e raw_input

Ora giunto il momento di definire funzioni nostre

Funzioni
Una funzione un blocco di istruzioni

Prevede una serie di parametri su cui eseguire le operazioni specificate

Ai parametri possono essere associati, ad ogni esecuzione, argomenti diversi


(e.g., il calcolo del discriminante)

Il paragone con le funzioni matematiche evidente

Definizione di una Funzione


Come in matematica, una funzione ha una intestazione e un corpo

Lintestazione definisce nome e dominio, ed il corpo (il codice vero e proprio)


fornisce il codominio ritornando un valore
def discriminante(a, b, c):
return b**2 - 4.0 * a * c

Corpo

Intestazione

Definizione di una Funzione


Il dominio indicato dai parametri nelle parentesi tonde nellintestazione

Il codominio nelle istruzioni di ritorno


def discriminante(a, b, c):
return b**2 - 4.0 * a * c

discriminante : R R R ! R

Uso delle funzioni


Definizione

def discriminante(a, b, c):


return b**2 - 4.0 * a * c

# Leggeremo i coefficienti

print "Eq.", a1, "x^2 + ", b1, "x + ", c1


print "Eq.", a2, "x^2 + ", b2, "x + ", c2

Prima chiamata

d1 = discriminante(a1, b1, c1)


d2 = discriminante(a2, b2, c2)

print d1, d2

Seconda chiamata

Dominio e Codominio
In Python le variabili hanno un tipo dinamico, ovvero possono cambiare tipo

legale assegnare ad una variabile, ad esempio, una stringa, e


successivamente un floating point

Linterprete comunica se nel chiamare una funzione i tipi siano coerenti con le
operazioni sui parametri

def discriminante(a, b, c):


return b**2 - 4.0 * a * c

print "discriminante = ", discriminante(-1.0, 2.0, "abc")


discriminante =
Traceback (most recent call last):
File "/Users/sensei/Desktop/aaa/a.py", line 14, in <module>
print "discriminante = ", discriminante(-1.0, 2.0, "abc")
File "/Users/sensei/Desktop/aaa/a.py", line 12, in discriminante
return b**2 - 4.0 * a * c
TypeError: can't multiply sequence by non-int of type 'float'

Semantica
Quando viene incontrata una chiamata ad una funzione, si interrompe
lesecuzione del programma

Avviene il passaggio dei parametri

Si avvia lesecuzione della funzione

Al termine dellesecuzione della funzione, riprende lesecuzione del


programma dallistruzione seguente alla chiamata

Passaggio di Parametri
Prima di iniziare lesecuzione della funzione, vengono identificati parametri
con argomenti
Eettivamente, i parametri delle funzioni sono delle variabili visibili solo
allinterno del corpo della funzione stessa

Lidentificazione termina alla conclusione dellesecuzione del sottoprogramma

Ad ogni chiamata dunque, gli argomenti variano

Questo comportamento identico a quanto accade in matematica

Passaggio di Parametri
f:

R
x

a=3

y = f (a)

!
7 !

R
2x

La variabile x avr come


valore il valore di a
La variabile x anche
se modificata non
avr effetto su a
Usando la funzione, di fatto
sar eseguito x = a

Passaggio di Parametri

def discriminante(a, b, c):


return b**2 - 4.0 * a * c

# Leggeremo i coefficienti

print "Eq.", a1, "x^2 + ", b1, "x + ", c1


print "Eq.", a2, "x^2 + ", b2, "x + ", c2

d1 = discriminante(a1, b1, c1)


d2 = discriminante(a2, b2, c2)
print d1, d2

Uso delle funzioni


programma

discriminante

a1

b1

c1

d1

return

Semantica
Questo processo di identificazione ha dierenze rispetto alla matematica

Di fatto, Python deve assegnare ad ogni parametro il valore dellargomento

In pratica, linterprete esegue automaticamente parametro = argomento

Cosa accade se una funzione ha come parametro una lista?

Come per ogni parametro, viene copiato largomento

Abbiamo visto per come le liste sono implementate: esiste un problema

Aliasing

Aliasing
def f(l):
for i in range(len(l)):
l[i] = 0

[1, 2, 3, 4]
[0, 0, 0, 0]

q = [1, 2, 3, 4]

print q
f(q)
print q

l = q
q

RAM

RAM

1 4

Aliasing
Chiamando una funzione con una lista, si incontra ancora laliasing

Una lista ricordiamo una porzione contigua di memoria che contiene


puntatori a dove sta il dato eettivo

Quando si chiama una funzione di fatto si copia il valore dellargomento

In questo caso, il valore una lista di puntatori

Inavvertitamente si pu modificare una variabile definita fuori dalla funzione


Bisogna prestare attenzione dunque al dominio, e se una lista, usare una
deep copy per evitare possibili eetti disastrosi

Codominio
Una funzione ha un dominio ed un codominio

Spesso, entrambi possono essere arbitrariamente complessi

Prendiamo in esempio le radici dellunit


Teorema fondamentale dellalgebra: un polinomio di grado n (a coecienti
complessi) ha esattamente n radici complesse

Esistono dunque esattamente n radici n-esime dellunit

Radici dellUnit
x

=(x)

1=0

Il polinomio ha
n radici complesse
radici : N
n=1
n=2
n=3
n=4

!C

+1
+1,
p 1
+1, 1/2( 1 + i 3), 1/2( 1
+1, 1, +i, i

<(x)
p

i 3)

Codominio
Un codominio complesso come lesempio precedente, ovvero RR nel caso
in cui n = 2, deve poter essere rappresentato

In questo caso, le tuple sono daiuto nel definire il codominio ed assegnare il


valore a due variabili

Le parentesi tonde, in questi casi, possono essere omesse, ma sono daiuto


per rendere leggibile il testo

def radici2():
return (1, -1)

def radici2():
return 1, -1

(r1, r2) = radici2()

r1, r2 = radici2()

print r1, r2

print r1, r2