# funcions i aleatorietat

Funcions en Python

Definir i cridar funcions que reben i retornen valors simples, treballar amb tuples i llistes dins de l'script, i generar nombres a l'atzar amb random — sense passar mai tuples ni llistes a cap funció.

Per què funcions?

Una funció és un bloc de codi amb nom, que pots cridar des de diversos llocs del programa sense repetir-lo. Ajuda a organitzar el codi en trossos petits, cadascun amb una sola responsabilitat.

Definició i crida

Sintaxi

def nom_funcio(paràmetres):
    # cos de la funció

Exemple

def saluda():
    print("Hola des de la funció!")

saluda()

Definir una funció no l'executa: el seu cos només corre quan algú la crida, escrivint el seu nom seguit de parèntesis. Fixa't que, a diferència de C, no cal dir el tipus de res: ni dels paràmetres ni del que retorna.

Paràmetres amb valor per defecte

def saluda(nom="desconegut"):
    print(f"Hola, {nom}!")

saluda()          # Hola, desconegut!
saluda("Jordi")   # Hola, Jordi!

Si no li passes aquest paràmetre, saluda fa servir el valor per defecte ("desconegut"). És una comoditat que C no té: allà, tots els paràmetres són sempre obligatoris.

Paràmetres: la funció rep el valor, no la variable

Quan passes una variable a una funció, dins la funció tens un nom nou (el paràmetre) amb aquell valor. Reassignar el paràmetre no toca la variable original.

Exemple

def incrementa(n):
    n = n + 1
    print(f"Dins de la funció: {n}")

x = 5
incrementa(x)
print(f"Fora de la funció: {x}")

La sortida és Dins de la funció: 6 i després Fora de la funció: 5 — exactament com en C. incrementa rep el valor de x (5) i el guarda en un nom propi, n; reassignar n no toca x per a res. Per intercanviar valors entre variables del cridant de debò (l'equivalent del que en C es fa amb apuntadors) caldrà una altra tècnica, que veurem més endavant.

return

Una funció pot retornar un valor amb return. return també talla l'execució de la funció a l'instant, encara que hi hagi més codi després.

Exemple

def quadrat(n):
    return n * n

resultat = quadrat(6)
print(f"El quadrat de 6 és {resultat}")

Si una funció no té cap return, o en té un sense valor (return tot sol), en realitat retorna None — l'equivalent Python d'una funció void de C.

Funcions que en criden d'altres

Una funció pot cridar qualsevol altra funció ja definida, incloent-hi funcions que tu mateix has escrit.

def quadrat(n):
    return n * n

def cub(n):
    return quadrat(n) * n

cub no recalcula n * n: reaprofita quadrat. Quan una funció en crida una altra, l'execució "puja" a la nova funció i, quan aquesta acaba, torna exactament al punt on l'havies cridat.

Tuples

Una tupla és una seqüència de valors fixa: un cop creada, no se'n poden afegir, treure ni canviar elements (és immutable).

Exemple

punt = (3, 7)
print(punt)

x, y = punt
print(x, y)

Pots desempaquetar-la directament en variables separades, com x, y = punt. De moment només la fem servir com a tipus de dada dins de l'script: no la passarem com a paràmetre ni la retornarem d'una funció — això té més sentit quan comparem amb els apuntadors de C.

Llistes

Una llista s'assembla a una tupla però és mutable: hi pots afegir, treure o canviar elements després de crear-la.

Exemple

notes = [7, 5, 9, 6]

suma = 0
for n in notes:
    suma = suma + n

print(f"Mitjana: {suma / len(notes):.2f}")

len(notes) dona el nombre d'elements. notes.append(valor) n'afegeix un al final. Igual que amb les tuples, de moment treballarem les llistes sempre dins del mateix script, sense passar-les mai com a paràmetre d'una funció.

Aleatorietat

El mòdul random genera nombres pseudoaleatoris.

Exemple: simular un dau

import random

dau = random.randint(1, 6)
print(f"Has tret un {dau}")

random.randint(a, b) retorna un enter entre a i b, tots dos inclosos. També existeix random.choice(llista), que n'escull un element a l'atzar.

Un avantatge sobre C

A diferència del rand() de C, el mòdul random de Python fa servir sempre el mateix algorisme (Mersenne Twister) a qualsevol sistema operatiu: el resultat no depèn de si estàs a Linux o a Windows. Això sí, com que és aleatori de debò, als exercicis només et demanarem comprovar propietats (per exemple, que surti entre 1 i 6), mai un número concret.

Mira el programa executar-se pas a pas

Fixa't sobretot en com l'execució "salta" a la funció quan es crida, i "torna" exactament al punt de la crida quan s'acaba.

Funcions

Tuples i llistes

Aleatorietat

Codi

Variables

NomValor

Terminal

Pas 1 / 1

Problemes per resoldre

Sense solució ni comprovació automàtica: escriu el programa, executa'l (python3 programa.py) i prova'l amb els exemples. Les funcions reben i retornen només valors simples; les llistes i tuples es queden sempre dins de l'script. Les pistes són plegades perquè les obris només si les necessites.

1. És parell?

Escriu una funció es_parell(n) que retorni True si n és parell i False si és senar. Demana un enter i mostra si és parell o senar fent servir aquesta funció.

Nombre: 7
És senar
Pistes

El cos pot ser una sola línia: return n % 2 == 0 — una comparació ja val True o False.

Crida la funció dins la condició d'un if: if es_parell(n):.

2. Any de traspàs

Escriu una funció es_traspas(any) que retorni True si l'any és de traspàs (divisible entre 4 però no entre 100, o bé divisible entre 400) i False si no. Prova-la amb diversos anys.

Any: 2024
És de traspàs

Any: 1900
No és de traspàs
Pistes

És la mateixa condició que potser ja vas escriure al capítol de condicionals — ara la poses dins d'una funció que la retorna.

return (any % 4 == 0 and any % 100 != 0) or any % 400 == 0

3. Àrea d'un cercle

Escriu una funció area_cercle(radi) que retorni l'àrea d'un cercle d'aquest radi (àrea = π · radi²). Demana el radi i mostra el resultat amb 2 decimals.

Radi: 3
Àrea: 28.27
Pistes

Pots fer servir math.pi (amb import math) en lloc d'escriure el valor de π a mà.

No t'oblidis de convertir el que llegeixis amb input() a float.

4. Compta sisos

Escriu una funció tira_dau() que retorni un valor a l'atzar entre 1 i 6. Tira el dau 20 vegades i compta (amb una variable comptador, sense desar res més) quantes vegades ha sortit un 6.

Sisos en 20 tirades: 4
Pistes

tira_dau pot ser una sola línia: return random.randint(1, 6).

Només et cal una variable comptador que comenci a 0 i s'incrementi cada cop que tira_dau() == 6. Com que el resultat és aleatori, no hi ha un número "correcte": qualsevol valor entre 0 i 20 és un resultat vàlid.

5. La nota més alta

Demana 5 notes a l'usuari (una per una) i desa-les en una llista amb append(). Un cop tens les 5, mostra la nota més alta — sense fer servir la funció max().

Nota 1: 6
Nota 2: 9
Nota 3: 4
Nota 4: 9
Nota 5: 7
La nota més alta és: 9
Pistes

Comença amb una llista buida (notes = []) i afegeix-hi cada nota llegida amb notes.append(nota).

Per trobar el màxim a mà: guarda la primera nota com a candidata (alta = notes[0]) i recorre la resta de la llista amb un for, actualitzant alta cada cop que trobis una nota més gran.

Exercicis d'autoavaluació

Aquests sí que es generen amb valors nous a l'atzar i tenen solució comprovable (no fan servir random, perquè aquest mai dona un valor fix per comprovar).

—

Quina serà la sortida per terminal d'aquest programa?