Python 3 per a no programadors/Definint funcions

Creant funcions[modifica]

Per començar aquest capítol us ensenyarem un exemple del que podríeu (però no hauríeu) de fer, per tant no cal que proveu aquest programa si no voleu:

a = 23
b = -23

if a < 0:
    a = -a
if b < 0:
    b = -b
if a == b:
    print("Els valors absoluts de", a, "i", b, "són iguals")
else:
    print("Els valors absoluts de", a, "i", b, "són diferents")

Que té com a sortida:

Els valors absoluts de 23 i 23 són iguals

(Recordeu que el valor absolut és un nombre sense tenir en compte el signe)

Aquest programa sembla una mica repetitiu. Els programadors odiem repetir coses (de fet per això tenim els ordinadors!). Fixeu-vos també que trobar el valor absolut ens ha canviat el valor de la variable, i per tant la sortida no és del tot clara. Per sort, Python ens permet crear funcions per a evitar repeticions. Aquí teniu el mateix exemple reescrit:

a = 23
b = -23

def valor_absolut(n):
    if n < 0:
        n = -n
    return n

if valor_absolut(a) == valor_absolut(b):
    print("Els valors absoluts de", a, "i", b, "són iguals")
else:
    print("Els valors absoluts de", a, "i", b, "són diferents")

i la sortida:

Els valors absoluts de 23 i -23 són iguals.

La paraula clau d'aquest programa és def. def (abreviació de define, definir) comença una definició de funció. def ve seguit del nom de la funció (en el nostre cas valor_absolut). Tot seguit venen els paràmetres que necessitem per a la funció entre parèntesis i separats per comes (en el cas anterior només n'hi ha un, n). Les ordres indentades després del símbol : s'executaràn quan es cridi la funció. La funció return retorna un valor al lloc on s'havia cridat. De fet ja vam veure una funció al primer programa, la funció print, que en aquest cas no retorna res. Ara podem definir noves funcions.

Fixeu-vos que els valors de a i b no canvien quan cridem la funció.

Les funcions es poden usar per a repetir tasques que no retornen res. Per exemple:

def hola():
    print("Hola")

def area(ample, alt):
    return ample * alt

def saluda(nom):
    print("Benvingut", nom)

hola()
hola()

saluda("Marc")
w = 4
h = 5
print("ample =", w, "alt =", h, "àrea =", area(w, h))

I la sortida:

Hola
Hola
Benvingut Marc
ample = 4 alt = 5 àrea = 20

Aquest exemple mostra algunes de les coses que es poden fer amb funcions. Tingueu en compte que podem fer o no fer servir arguments i que podem retornar o no un valor

Variables en funcions[modifica]

Quan eliminem codi repetit, ens queden sovint variables en el codi repetit. En Python, aquestes variables es tracten de manera una mica diferent. Fins ara totes les variables que hem vist eren globals. Les funcions tenen un tipus especial de variables anomenades locals. Aquestes només existeixen mentre la funció s'està executant. Quan una variable local té el mateix nom que una de global la variable local amaga l'altra. Us sembla estrany? Aquests exemples us haurien d'aclarir les coses.

a = 4
 
def print_func():
    a = 17
    print("a print_func a = ", a)

print_func()
print("a = ", a)

Que genera aquesta sortida:

a print_func a = 17
a = 4

Les assignacions fetes dins una funció, no modifiquen les variables globals, ja que només existeixen dins la funció. Tot i que hàgim assignat un nou valor a a, aquest només afecta a print_func, i quan aquesta funció acaba, veiem el valor original de la variable.

Aquí tenim un exemple una mica més complex.

a_var = 10
b_var = 15
e_var = 25

def a_func(a_var):
    print("a a_func a_var = ", a_var)
    b_var = 100 + a_var
    d_var = 2 * a_var
    print("a a_func b_var = ", b_var)
    print("a a_func d_var = ", d_var)
    print("a a_func e_var = ", e_var)
    return b_var + 10

c_var = a_func(b_var)

print("a_var = ", a_var)
print("b_var = ", b_var)
print("c_var = ", c_var)
print("d_var = ", d_var)


Les tres primeres instruccions del programa en executar-se creen les variables a_var , b_var, i d_var i els assignen respectivament els valors 10, 15 i 25.

La instrucció def a_func(a_var): és una definició de funció i no s'executa.

La instrucció c_var = a_func(b_var) crida la funció que s'ha definit abans (a_func) passant-li com argument el valor de la variable b_var que en aquest moment és 15 perquè això és el que li ha assignat la segona instrucció. Compte que el que li passa és el valor de la variable, no la variable. El valor que retorna la funció s'emmagatzema en la variable c_var que és la primera vegada que apareix, per tant es crea ara.

Com que ha estat cridada ara sí que s'executa la funció a_func Dins de la funció el valor que rep com a paràmetre ( un 15) l'emmagatzema en una variable que es diu a_var. Compte que aquesta és una variable local que es crea en aquest moment i que no afecta res del que hi hagi fora de la funció. Al sortir de la funció la variable del mateix nom que s'ha creat a la primera instrucció continuarà amb el mateix valor que tenia abans de cridar a la funció, és a dir 10 i no 15 que és el valor que conté la variable del mateix nom dins de la funció. Tot seguit la funció imprimeix per pantalla el valor que té la variable a_var (això és el primer que hi ha a la sortida), després crea les variables locals b_var i d_var i els assigna respectivament els valors 115 (100 + 15) i 30 (2*15). Això és el que apareix a la tercera i quarta línia de la sortida degut a les corresponents instruccions print de la funció. Fixeu-vos que la variable b_var també té el mateix nom que una variable que hi ha fora de la funció però tampoc es veurà afectada, per tant fora continuarà contenint un 15 i no un 115. La següent instrucció dins de la funció és imprimir el valor de la variable e_var. Com que a aquesta variable no li ha estat assignat cap valor dins de la funció, conserva el que tenia fora de la funció, per això apareix un 25 a la següent línia de la sortida. Lo últim que fa la funció és retornar el valor 125 (115 + 10). 115 és el valor que dins de la funció en aquest moment conté la variable b_var.

Un cop fora de la funció s'imprimeixen els valors que contenen aquí les variables:

a_var dóna 10 perquè és el valor que se li va assignar al començament i fora de la funció no ha estat mai alterat. b_var dóna 15 pel mateix motiu. c_var dóna 125 perquè és un s'ha emmagatzemat el valor que ha retornat la funció. d_var dóna error perquè aquesta variable no ha estat creada.


En aquest exemple les variables a_var , b_var, i d_var , són totes les variables locals quan estan dins de la funció a_func .

Després de la declaració return b_var + 10 s'executa, totes deixen d'existir.

La variable a_var és automàticament una variable local ja que és un nom de paràmetre. Les variables b_var i d_var són locals, ja que apareixen a l'esquerra d'un signe d'igualtat en les declaracions b_var = 100 + a_var i d_var = 2 * a_var .

Dins de la funció a_var no hi ha cap valor assignat. Quan la funció és cridada a c_var = a_func(b_var), s’assigna 15 a a_var ja que en aquest punt b_var és 15, cridant a la funció a_func(15) .

Acaba posant a_var a 15 quan és dins d' a_func.

Com podeu veure, quan la funció s'acaba d'executar, les variables locals a_var i b_var que havien amagat les variables globals del mateix nom han desaparegut. A continuació, la declaració print ("a_var =", a_var) imprimeix el valor 10 en lloc de 15 , ja que la variable local que amagava la variable global ha desaparegut.

Una altra cosa a notar és el NameError que passa al final. Això apareix ja que d_var variable ja no existeix, des que a_func ha acabat. Totes les variables locals s'esborren quan la funció finalitza. Per obtenir informació d'una funció, llavors haureu d'utilitzar return something.

Una última cosa a notar és que el valor de e_var es manté sense canvis dins de a_func, ja que no és un paràmetre i mai apareix a l'esquerra d'un signe d'igualtat dins de la funció a_func. Quan una variable global és consultada dins d'una funció és manté la variable global de l'exterior.

Exemples[modifica]

temperature2.py

# converts temperature to Fahrenheit or Celsius

def print_options():
    print("Options:")
    print(" 'p' print options")
    print(" 'c' convert from Celsius")
    print(" 'f' convert from Fahrenheit")
    print(" 'q' quit the program")

def celsius_to_fahrenheit(c_temp):
    return 9.0 / 5.0 * c_temp + 32

def fahrenheit_to_celsius(f_temp):
    return (f_temp - 32.0) * 5.0 / 9.0

choice = "p"
while choice != "q":
    if choice == "c":
        temp = float(input("Celsius temperature: "))
        print("Fahrenheit:", celsius_to_fahrenheit(temp))
    elif choice == "f":
        temp = float(input("Fahrenheit temperature: "))
        print("Celsius:", fahrenheit_to_celsius(temp))
    elif choice == "p": #Alternatively choice != "q": so that print when anything unexpected inputed
        print_options()
    choice = input("option: ")

Sortida:

Options:
 'p' print options
 'c' convert from celsius
 'f' convert from fahrenheit
 'q' quit the program
option: c
Celsius temperature: 30 
Fahrenheit: 86.0
option: f
Fahrenheit temperature: 60
Celsius: 15.5555555556
option: q

area2.py

# By Amos Satterlee
print
def hello():
    print('Hello!')

def area(width, height):
    return width * height

def print_welcome(name):
    print('Welcome,', name)

def positive_input(prompt):
    number = float(input(prompt))
    while number <= 0:
        print('Must be a positive number')
        number = float(input(prompt))
    return number

name = input('Your Name: ')
hello()
print_welcome(name)
print()
print('To find the area of a rectangle,')
print('enter the width and height below.')
print()
w = positive_input('Width: ')
h = positive_input('Height: ')

print('Width =', w, 'Height =', h, 'so Area =', area(w, h))

Que produeix:

Your Name: Josh
Hello!
Welcome, Josh

To find the area of a rectangle,
enter the width and height below.

Width: -4
Must be a positive number
Width: 4
Height: 3
Width = 4 Height = 3 so Area = 12

Exercici[modifica]

Torna a escriure el programa area2.py des dels exemples de dalt, separant la funció de l’àrea d’un quadrat, l’àrea d’un rectangle, i l’àrea del cercle (3.14 * radius**2). Aquest programa inclou una interfície de menú.