Am văzut până acum că, dacă dorim să executăm aceleași instrucțiuni de mai multe ori, fie le scriem de mai multe ori, fie creăm o funcție și o apelăm de mai multe ori. În cazul funcțiilor, am văzut că putem avea parametri astfel încât am putea avea variații asupra modului în care se execută instrucțiunile din corpul funcției.
Dar, aceste soluții au un impediment. Trebuie să știm exact de câte ori vrem să executăm acele instrucțiuni și fie să le scriem de atâtea ori, fie să apelăm de atâtea ori o funcție care le conține. Ce facem dacă nu știm exact de câte ori vrem să fie executate?
De exemplu, am putea dori să scriem cifrele unui număr. Vom avea, probabil, o instrucțiune care va scrie o cifră și un mecanism prin care acesta va fi apelată. Dar, în funcție de cât de mare este acel număr, numărul execuțiilor va varia. Pentru numărul 2457 instrucțiunea se va executa de patru ori, dar pentru 47 doar de două ori.
Am văzut în episodul VIII că pentru a determina ultima cifră a unui număr este suficient să calculăm restul împărțirii acelui număr la zece. Putem observa că, practic, printr-o împărțire întreagă (calcularea câtului împărțirii) la zece eliminăm acea cifră din număr. Restul împărțirii noului număr la zece ne va da penultima cifră a numărului inițial; o nouă împărțire întreagă la zece va elimina și această cifră. Continuăm până se termină cifrele, adică atâta timp cât rezultatul împărțirii la zece va fi mai mare decât zero.
Vom avea cifrele în ordine inversă, dar ne vom mulțumi cu acest lucru deocamdată; de asemenea, nu va funcționa pentru numere negative și nici pentru numărul zero (vom crede că nu există nicio cifră).
Limbajul Python ne pune la dispoziție o construcție care permite executarea unei instrucțiuni atâta timp cât o anumită condiție este adevărată. Evident, instrucțiunea respectivă poate fi un bloc de instrucțiuni. La fel ca în cazul instrucțiunii if (a se vedea episodul IV) se păstrează recomandarea de a avea un bloc format dintr-o singură instrucțiune în locul unei instrucțiuni simple.
Instrucțiunea while
Dar, care este noua instrucțiune? Pentru a explica ce vrem să facem, am folosit cuvintele atâta timp; am spus că atâta timp cât o anumită condiție este îndeplinită vom efectua o anumită acțiune. Și în Python vom folosi ceva similar; va fi în engleză, deci cuvântul va fi while. El va fi urmat de condiția care trebuie verificată (parantezele rotunde sunt opționale), iar apoi de instrucțiunea care trebuie executată cât timp condiția este îndeplinită. Condiția este o expresie booleană; poate fi o simplă variabilă sau o expresie mai complexă. O astfel de instrucțiune este numită iterativă. Mai sunt folosite și denumirile de instrucțiune repetitivă sau buclă. Instrucțiunile executate atâta timp cât este îndeplinită condiția sunt numite și corpul buclei.
Putem scrie acum secvența care afișează cifrele unui număr (în ordine inversă)...
1 2 3 4 |
n = 2457 while n > 0: print(n % 10) n /= 10 |
Astfel de instrucțiuni pot apărea oriunde; de exemplu, ar putea fi parte a unui bloc de instrucțiuni (în interiorul unui alt while, al unui if, al unei funcții etc.). Să vedem cum facem o funcție care să afișeze cifrele unui număr:
1 2 3 4 |
def cifre(n): while n > 0: print(n % 10) n /= 10 |
Observăm că este posibil ca blocul de instrucțiuni care formează bucla să nu se execute niciodată în cazul în care condiția nu este îndeplinită la prima verificare. Acest lucru s-ar întâmpla dacă am apela funcția de mai sus transmițând ca argument un număr negativ sau zero.
De asemenea, trebuie să avem în vedere că în corpul buclei trebuie să existe la un moment dat ceva care afectează condiția care este evaluată. Altfel, aceasta va rămâne tot timpul adevărată (dacă a fost prima dată) și corpul său se va executa la infinit dacă nu este înterupt prin alt mecanisme (de exemplu printr-un return).
While în while
Am spus că instrucțiunea while poate apărea oriunde. De exemplu, ar putea fi parte a blocului de instrucțiuni al unei alte instrucțiuni while. Să încercăm să scriem un program care afișează tabla înmulțirii până la zece. Vom avea numerele de la unu la zece ca prim factor și, pentru fiecare dintre acestea, numerele de la unu la zece ca al doilea factor. Să vedem cum ar arăta o funcție care ar realiza acest lucru:
1 2 3 4 5 6 7 8 9 10 |
def tabela_inmultirii(): factor1 = 1 while factor1 <= 10: factor2 = 1 linie = "" while factor2 <= 10: linie += "\t" + str(factor1 * factor2) factor2 += 1 print(linie) factor1 += 1 |
Am separat valorile prin taburi pentru a le alinia puțin mai frumos. Așa cum există caracterul special pentru sfârșit de linie, există și un caracter special pentru tab; acesta este \t. Dacă este apelată funcția de mai sus, la ieșire vom avea ceva de genul:
1 2 3 4 5 6 7 8 9 10 |
1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100 |
Mai trebuie să observăm că variabilele factor2 și linie sunt declarate și utilizate în interiorul primei bucle. Domeniul de vizibilitate al acestor variabile este doar în blocul de instrucțiuni care formează corpul buclei; pentru fiecare execuție a corpului primei bucle, vor fi declarate și utilizate variabile noi, care nu are nicio legătură cu variabilele cu același nume declarate și utilizate în timpul execuțiilor anterioare sau ulterioare. Ar mai trebui menționat faptul că am folosit funcția str care transformă un număr întreg într-un string.
Va urma
În episodul următor vom prezenta o altă instrucțiune repetitivă care simplifică puțin codul în anumite situații.