Estructura repetitiva for in
En aquesta lliçó aprendreu a utilitzar un altre tipus d’estructura repetitiva: el bucle for in. És semblant a l’estructura del while i s’utilitza igualment per a generar repeticions. Tot el que es pot fer amb un bucle for in també es pot fer amb un bucle while, però moltes vegades és més fàcil utilitzar el for in.
A la inversa no és veritat: hi ha programes que es poden fer amb un while però no amb el bucle for in (sense recórrer a les instruccions de programació no estructurada com break i continue).
For in
El bucle for in es fa servir sobretot per a les repeticions si sabeu la quantitat de vegades que voleu executar el cicle (per comptar, per exemple), o si coneixeu els elements concrets sobre els quals voleu fer les accions repetides.
range() en Python2 era una funció que retornava una llista. En Python3 s’ha convertit en una classe, o un nou tipus de dada, però l’únic que cal que recordeu és que proporciona una estructura que podeu utilitzar com si fos una llista.
Primer programa amb el bucle for in
Feu o recordeu el següent programa: escriure els 5 primers múltiples de 2 (començant per 0). Una versió d’aquest programa amb el bucle while seria aquesta:
i = 0 while i < 5: multiple = 2 * i print(multiple) i = i + 1
Fixeu-vos ara en el següent programa: fa exactament el mateix que l’anterior, però utilitza una nova modalitat de bucle: el bucle for in:
for i in [0, 1, 2, 3, 4]: multiple = 2 * i print(multiple)
Literalment “for in” vol dir “per a tots els elements” d’una successió.
El bucle for in repeteix unes instruccions (el cos del bucle), per tots els elements d’una seqüència. En la primera repetició, la variable pren el valor del primer element, i passa al següent reiteradament fins que arriba a l’últim. En aquest moment és quan el flux del programa surt del bucle for in.
for variable in seqüència: cos del bucle
D’entrada aquest darrer programa sembla més senzill que l’anterior (hi ha menys línies i menys variables). Això és així perquè el bucle for in està especialment indicat per a ser utilitzat quan ja se saben la quantitat de repeticions que es necessiten, i no cal verificar cap condició abans de sortir.
La figura mostra el codi com es visualitza a l’editor.
La novetat està en l’estructura de la línia 11: el bucle for in, que recorre un tipus nou per a vosaltres: les dades de tipus llista.
Una llista és un tipus de dada: es tracta d’una seqüència d’elements, que s’escriuen dins dels símbols [ i ] i van separats per comes. Si aquests elements són enters, és una llista d’enters. També pot haver-hi llistes de strings, llistes de llistes o llistes de molts altres tipus de dades.
Aquestes són les explicacions, línia a línia, del programa:
- Les instruccions del cos del bucle (el que està a dins o indentat, és a dir les línies 12 i 13) es repeteixen per a cada un dels elements de la llista de la línia 11.
- En aquest cas els elements de la llista són els enters 0, 1, 2, 3 i 4. Estan ordenats (en el sentit que cadascun ocupa una posició), i s’escriuen un darrere l’altre separats per una coma.
- El nombre zero és el primer element de la llista, el nombre 1 és el segon, etc.
- El que fa el bucle
for inés fer una repetició del cos del bucle per a cada element de la llista, “carregant” en cada cas a la variable definida (laien aquest exemple) el valor que li toca. En la 1a volta laipren el valor del primer element (0 en aquest exemple), en la segona la del segon i així fins a arribar a l’últim.
El seguiment el teniu recollit a la taula:
| Núm. fila | Llista | i | Múltiple | Sortida |
|---|---|---|---|---|
| 11 | [0, 1, 2, 3, 4] | 0 | ||
| 12 | 0 | |||
| 13 | 0 | |||
| 11 | 1 | |||
| 12 | 2 | |||
| 13 | 2 | |||
| 11 | 2 | |||
| 12 | 4 | |||
| 13 | 4 | |||
| 11 | 3 | |||
| 12 | 6 | |||
| 13 | 6 | |||
| 11 | 4 | |||
| 12 | 8 | |||
| 13 | 8 |
El procés és el següent:
- Quan el programa troba un bucle
for inper primera vegada (en aquest exemple és la primera instrucció), es fan tres coses:- Es crea internament una llista, que s’anirà recorrent per anar donant els diferents valors a la variable.
- Es crea una variable amb el nom que s’indica en el bucle (
i, en l’exemple). - S’inicialitza el valor de la variable amb el primer element de la llista.
- Després s’executen les instruccions del cos del bucle, amb el valor que s’ha donat a la variable
i. - Cada vegada que finalitza el cos del bucle, torna a començar, assignant a la variable i el valor del següent element.
- En finalitzar la llista, surt del bucle i continuaria amb les instruccions que no estan indentades (en aquest exemple no n’hi ha).
Operador in
En aquest punt convé fixar-se en l’operador in, que es pot utilitzar a banda del bucle for in.
Els operadors in, i not in són operadors de dades de tipus seqüencial (les llistes són seqüències). Indiquen si un element està o no en una seqüència. El resultat és una dada booleana.
element in seqüència
Operadors ''in'' i ''not in''
Entreu a l’intèrpret interactiu i executeu els següents exemples, que us ajudaran a entendre aquests operadors:
>>> llista = [1, 2, 5, 7] >>> 3 in llista False >>> 7 not in llista False >>> 7 in llista True
Exemple: programa del compte enrere
Escriviu un programa que faci un compte enrere (a partir de 3). El programa ha de mostrar:
3 2 1 0 BUUUM
Amb el bucle for, el programa és més simple que amb el while:
for i in [3, 2, 1, 0]:
print(i)
print('BUUUM')
La figura mostra el codi com es mostra a l’editor.
El seguiment el teniu recollit a la taula.
Però què passa si voleu fer el compte enrere des del nombre 100? Cal escriure una llista amb tots els nombres? O si voleu poder triar a partir de quin nombre comença el compte enrere?
| Núm. línia | Llista | i | Sortida |
|---|---|---|---|
| 9 | [3, 2, 1, 0] | 3 | |
| 10 | 3 | ||
| 9 | 2 | ||
| 10 | 2 | ||
| 9 | 1 | ||
| 10 | 1 | ||
| 9 | 0 | ||
| 10 | 0 | ||
| 12 | BUUUM |
Objecte range
Per començar, busqueu què diu l’ajuda sobre range() (és builtin o del sistema, o sigui que no cal importar cap mòdul). Escriviu a l’intèrpret interactiu:
help(range)
Obteniu una pàgina que comença per:
range() en Python2 era una funció que retornava una llista. En Python3 s’ha convertit en una classe, o un nou tipus de dada, però l’únic que cal que recordeu és que proporciona una estructura que podeu utilitzar com si fos una llista.
Help on class range in module builtins: class range(object) | range(stop) -> range object | range(start, stop[, step]) -> range object | | Return an object that produces a sequence of integers from start (inclusive) | to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1. | start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3. | These are exactly the valid indices for a list of 4 elements. | When step is given, it specifies the increment (or decrement). | | Methods defined here:
El primer que diu l’ajuda és que es tracta d’una classe, no d’una funció. A més, és una classe del mòdul buitlins (és a dir, que no s’ha d’importar per utilitzar-la). Explica com crear objectes, passant-li un, dos o tres arguments.
El tipus range és com una llista immutable de nombres enters en successió aritmètica. En definitiva, l’utilitzareu com una llista. Com sempre, per aprendre i provar com funcionen les coses, el millor és anar a l’intèrpret interactiu.
>>> range(10) range(0, 10) >>> a = range(10) >>> list(a) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
D’entrada, s’ha creat un objecte range (utilitzant un argument), i s’ha mostrat. El primer que diu l’intèrpret interactiu (range(0, 10)), indica és que s’ha creat un objecte range, i que és el mateix que si s’hagués construït amb els arguments 0 i 10.
La funció list(), intenta convertir l’argument a llista, sempre i quan li sigui possible. És una funció anàloga a les funcions int(), float(), str() i bool() que ja coneixeu.
En els següents passos es crea de nou aquest objecte, però s’assigna a una variable que es converteix en llista. No entrarem en detalls sobre el que fa aquest objecte, però el que necessiteu saber és que s’utilitza per a generar una seqüència de valors, alguna cosa tan semblant a una llista de nombres que només cal aplicar-hi la funció list() perquè ho sigui.
Ara interessa que us fixeu fixeu en els elements d’aquesta llista. Efectueu les següents instruccions:
>>> a = range(10) >>> list(a) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> >>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(1, 10)) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(0, 10, 3)) [0, 3, 6, 9]
Segons la documentació, es pot utilitzar el constructor amb un únic argument: range(stop), amb dos arguments: range(start, stop), o amb tres: range(start, stop, step).
Observeu que la llista comença pel nombre start (o zero si es crida amb un sol argument), i acaba abans del nombre stop (start i stop són els noms dels arguments que indica la documentació).
Per obtenir els elements intermedis es va sumant el tercer argument a l‘start (step, si hi és). Si no hi ha tercer argument, per defecte es considera que el pas o step és 1.
L’objecte range() és una estructura semblant una llista d’enters. Es pot construir amb un, dos o tres arguments (que han de ser nombres enters):
range(stop)comença en el zero i acaba en l’enter anterior a stop. La llista està formada per nombres enters consecutius.range(start, stop)comença en el nombre enter start i acaba en l’enter anterior a stop. La llista també està formada per nombres enters consecutius.range(start, stop, step)el primer element és l’enter start, acaba abans de l’enter stop, i per passar de cada nombre al següent s’afegeix la quantitat step.
Escriure els 5 primers múltiples de dos (començant per 0)
El codi del programa dels múltiples de 2, utilitzant range, seria el següent:
N = 5 BASE = 2 for i in range(0, N): multiple = BASE * i print(multiple)
Observeu que ja podeu utilitzar constants per a definir la quantitat de múltiples que voleu. També se n’ha utilitzat una altra perquè pugui servir per a escriure els múltiples de qualsevol nombre.
El seguiment que podem veure a la taula, és pràcticament igual al de la primera versió:
| Núm. fila | N | Base | Llista | i | Múltiple | Sortida |
|---|---|---|---|---|---|---|
| 8 | 5 | |||||
| 9 | 2 | |||||
| 11 | [0, 1, 2, 3, 4] | 0 | ||||
| 12 | 0 | |||||
| 13 | 0 | |||||
| 11 | 1 | |||||
| 12 | 2 | |||||
| 13 | 2 | |||||
| 11 | 2 | |||||
| 12 | 4 | |||||
| 13 | 4 | |||||
| 11 | 3 | |||||
| 12 | 6 | |||||
| 13 | 6 | |||||
| 11 | 4 | |||||
| 12 | 8 | |||||
| 13 | 8 |
Compte enrere amb range
Abans de començar, executeu en l’intèrpret interactiu l’ordre:
>>> list(range(10, 0, -1)) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
No heu de tenir problemes en interpretar el següent codi:
num = int(input())
for i in range(num, -1, -1):
print(i)
print('BUUUM')
start: els nombres generats han de començar amb el valornum(que s’ha llegit).stop: com que l’últim nombre mostrat ha de ser el zero, el valorstopha de valer -1 (sempre es finalitza en l’enter anterior astop).step: cal que els nombres vagin disminuint d’un en un. Per això el valorstepha de ser -1.
Range i inicialització de la variable del bucle
Què passa si es construeix un objecte range però no hi ha enters que compleixin les condicions d’estar entre els enters start i stop?
Comproveu amb l’intèrpret interactiu el resultat de les següents instruccions:
L’enter 2 i la llista [2] no són el mateix. Son tipus de dades diferents (una és de tipus enter i l’altra és de tipus llista). Comproveu el resultat de la instrucció:
»> 2 == [2]
>>> list(range(0, 3)) [0, 1, 2] >>> list(range(2, 3)) [2] >>> list(range(3, 3)) []
En el primer exemple, el resultat és una llista amb 3 enters. En el segon exemple, l’intèrpret respon amb una llista que conté un únic element. I el resultat de la 3a instrucció és una llista que no conté cap element. S’anomena llista buida.
Què passa quan en un programa apareix un bucle for amb una llista buida? Feu el seguiment per a aquest fragment de programa:
for i in range(0): print(i) print(I)
A continuació teniu la figura amb les línies numerades:
El seguiment serà similar al que teniu a la taula:
| Núm. línia | llista | i | sortida |
|---|---|---|---|
| 3 | [] | ||
| 6 | Error |
En la línia 3 es troba el for in. En crea una “llista” (no és ben bé una llista sinó un objecte range), que en aquest cas no conté res. No s’entra en el bucle for in perquè no hi ha elements per als quals fer el cos del bucle. Però això comporta que tampoc es crea la variable i (ja que no hi ha cap element per a inicialitzar-la).
Si en algun moment s’intenta accedir a aquesta variable s’obté un missatge d’error perquè no ha estat definida.
videoioc@debian-xtec:~/Documents/programacio$ python3 seguiment.py
Traceback (most recent call last):
File "/home/videoioc/Documents/programacio/seguiment.py", line 6, in <module>
print(i)
^
NameError: name 'i' is not defined. Did you mean: 'id'?
Repeticions per a valors concrets
Fins ara heu vist com s’utilitza el bucle for in per generar repeticions quan sabeu la quantitat de vegades, o quan els valors es poden presentar en forma de successió aritmètica. En els dos casos, s’utilitza el bucle for in acompanyat de range.
Però és possible que necessiteu programar la repetició d’unes instruccions, i que els valors de la variable hagin d’anar prenent i no es puguin definir amb l’objecte range.
Repartir una quantitat de diners en el menor nombre possible de bitllets
Heu d’escriure un programa que reparteixi una quantitat de diners en el menor nombre possible de bitllets. En aquest cas, heu de fer les mateixes operacions per als valors de diferents tipus de bitllets: 500, 200, 100, etc. I no els podeu escriure utilitzant range. En aquestes situacions haureu d’escriure la llista de valors que s’han d’utilitzar. El codi del programa seria:
euros = int(input()) for valor in [500, 200, 100, 50, 20, 10, 5, 2, 1]: quantitat = euros // valor euros = euros % valor print(quantitat, 'bitllets de', valor, 'euros' )
Conceptes clau de la lliçó
Tenir clars els aspectes clau de l’estructura iterativa for in us permetrà fer programes correctes i controlar amb precisió el seu flux. A continuació us ressaltem els punts més importants perquè els tingueu com a referència.
Bucle for in
El bucle for in repeteix unes instruccions (el cos del bucle), per tots els elements d’una seqüència. En la primera repetició, la variable pren el valor del primer element, i passa al següent reiteradament fins que arriba a l’últim. En aquest moment és quan el flux del programa surt del bucle for in.
for variable in seqüència: cos del bucle
Operadors in i not in
Els operadors in, i not in són operadors de dades de tipus seqüencial (les llistes són seqüències). Indiquen si un element està o no en una seqüència. El resultat és una dada booleana.
element in seqüència
Objecte range
En molts casos s’utilitza el bucle for in amb range, quan se sap exactament la quantitat de repeticions que s’han d’efectuar o quan els elements pels quals s’han de repetir les instruccions del cos del bucle es poden escriure com a una successió aritmètica. En aquest cas, l’estructura del bucle for in és:
range() en Python2 era una funció que retornava una llista. En Python3 s’ha convertit en una classe, o un nou tipus de dada, però l’únic que cal que recordeu és que proporciona una estructura que podeu utilitzar com si fos una llista.
for variable in range(start, stop):
# instruccions del cos del bucle
Altres usos del bucle for in
En aquesta lliçó s’ha utilitzat el bucle for in per a iterar llistes de nombres enters. Amb aquest bucle es poden recórrer llistes de qualsevol tipus de dades (com llistes de cadenes), els caràcters d’una cadena o qualsevol altre tipus que tingui la característica de ser iterable.
En Python, una classe és iterable quan pot ser iterada (o recorreguda). Exemples de classes iterables son les seqüències (com les llistes o les cadenes), però també hi ha objectes no seqüencials que ho son, com els diccionaris






