Python 3 per a no programadors/Exemple de funció avançada

Hi ha gent que troba aquesta secció útil i altra que la troba confusa. Si la trobeu confusa podeu passar a la següent (o simplement mirar els exemples).

Ara farem un passeig pel programa següent:

def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
print "3 * 2 = ", mult(3, 2)

Bàsicament aquest programa crea una funció de multiplicació d'enters positius (que és força més lenta que la funció de multiplicació existent). A continuació es mostra com s'utilitza aquesta funció. Aquest programa és un exemple de la utilització de la recursivitat, que és una forma de repetició en la que hi ha una funció que repetidament es crida a si mateixa fins que es produeix una condició perquè finalitzi. Fa servir addicions repetides per donar el mateix resultat que una multiplicació: p. ex. 3 + 3 (addició) dóna el mateix resultat que 3 * 2 (multiplicació).

Pregunta: Què és el primer que fa el programa?
Resposta: La primera acció que fa és definir la funció mult a les línies:
def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
Això crea una funció que agafa dos paràmetres i retorna un valor quan s'executa. Posteriorment es podrà fer servir aquesta funció.
Què passa a continuació?
S'executa la línia posterior a la funció, print("3 * 2 = ", mult(3, 2)).
I què fa això?
Escriu 3 * 2 = i el valor resultant de mult(3, 2)
I quin és el valor de la funció mult(3, 2) ?
Per veure-ho hem d'anar observant pas a pas la funció mult.
Què passa a continuació?
La variable a passa a tenir el valor 3 que se li ha assignat i la variable b passa a tenir el valor 2 assignat.
I aleshores?
La línia if b == 0: s'executa. Des del moment en què la variable b té el valor 2 això és fals per la qual cosa es salta la línia return 0.
I després?
S'executa la línia rest = mult(a, b - 1). Aquesta línia estableix per la variable local rest el valor de mult(a, b - 1). El valor d' a és 3 i el valor de b és 2, de manera que la funció s'aplica a mult(3,1)
I quin és el valor de mult(3, 1) ?
Necessitarem executar la funció mult amb els paràmetres 3 i 1.
I què passa a continuació?
Les variables locals per la nova execució de la funció queden establertes amb el valor 3 per la variable a i el valor 1 per la variable b. Com que aquests valors són locals no afecten els valors previs d'a i b.
I aleshores?
Com que la variable b té com a valor 1, la declaració if és falsa, per la qual cosa la següent línia passa a ser rest = mult(a, b - 1).
Què fa aquesta línia?
Aquesta línia assignarà el valor de mult(3, 0) a la resta.
I quin és aquest valor?
Haurem d'executar la funció una vegada més per trobar-ho. Aquesta vegada a té com a valor 3 i b val 0.
Què passa ara?
La primera línia que s'executa de la funció és if b == 0:. b té com a valor 0 de manera que la següent línia en executar-se és return 0
I què fa la línia return 0?
Aquesta línia retorna el valor 0 per la funció.
I?
Doncs ara sabem que mult(3, 0) té com a valor 0. També sabem què ha fet la línia rest = mult(a, b - 1) des que hem executat la funció mult amb els paràmetres 3 i 0. Hem acabat d'executar mult(3, 0) i tornem a executar mult(3, 1). S'assigna el valor 0 a la variable rest.
Quina línia s'executa a continuació?
S'executa la línia value = a + rest. En aquesta execució de la funció, a = 3 i rest = 0 per la qual cosa value = 3.
Què passa ara?
S'executa la línia return value. Això dóna 3 com a resultat de la funció. Això també surt de l'execució de la funció mult(3, 1). Després de cridar return, es torna a l'execució de mult(3, 2).
On érem a mult(3, 2)?
Teníem les variables a = 3 i b = 2 i erem fixant-nos en la línia rest = mult(a, b - 1).
I què passa ara?
S'assigna el valor 3 a la variable rest. La línia següent value = a + rest estableix value com a 3 + 3 o 6.
I ara què passa?
S'executa la següent línia, que retorna el valor 6 com a resultat de la funció. Tornem ara a executar la línia print("3 * 2 = ", mult(3, 2)) que retorna el 6.
Què és el que hem fet aplicant aquesta funció a partir dels paràmetres especificats?
Bàsicament hem fet servir dos fets per calcular el múltiple de dos números. El primer és que qualsevol número multiplicat per 0 és 0 (x * 0 = 0). El segon és que el producte d'un número per un altre és igual al primer número més el primer número multiplicat pel segon menys 1 (x * y = x + x * (y - 1)). De manera que el que passa és que 3 * 2 es converteix incicialment en 3 + 3 * 1. A continuació 3 * 1 es converteix en 3 + 3 * 0. Sabent que qualsevol número per 0 és 0 aleshores 3 * 0 és 0. I podem calcular que 3 + 3 * 0 és 3 + 0 que és 3. Ara sabem quan és 3 * 1 per la qual cosa podem calcular que 3 + 3 * 1 és 3 + 3 que és 6.

Així és com funciona tot plegat:

3 * 2
3 + 3 * 1
3 + 3 + 3 * 0
3 + 3 + 0
3 + 3
6


Recursió modifica

Les construccions de programari d'aquest tipus s'anomenen recursives. Per més aclariments vegeu recursió.

Recursió
Si encara no ho enteneu, vegeu recursió.

Podeu observar el funcionament de l'exemple amb el factorial si no heu acabat d'entendre l'anterior exemple de multiplicació.

Exemples modifica

factorial.py

#defineix una funció que calcula el factorial

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print("2! =", factorial(2))
print("3! =", factorial(3))
print("4! =", factorial(4))
print("5! =", factorial(5))

Resultat:

2! = 2
3! = 6
4! = 24
5! = 120

countdown.py

def count_down(n):
    print(n)
    if n > 0:
        return count_down(n-1)

count_down(5)

Resultat:

5
4
3
2
1
0