9. PLEINE PUISSANCE

9.1. Boucle généralisée: le while

Le for ne permet pas de programmer tous les traitements. En effet, il impose de connaître avant de commencer à exécuter une boucle le nombre de fois où celle-ci devra être parcourue (ou au moins pouvoir fixer le nombre maximum d’itérations). Lorsque l’on ne connaît pas a priori le nombre d’itérations à réaliser, il faut une structure de contrôle plus générale. C’est ce que permet le while.

Sa forme est:

while CONDITION:
  TRAITEMENT

La partie TRAITEMENT indentée contient les instructions à réaliser dans la boucle. Ces instructions sont répétées tant que l’expression CONDITION est satisfaite, et lorsque CONDITION vaut faux alors l’exécution continue après la boucle.

Warning

La condition est testée avant chaque itération, et la boucle se termine lorsque la condition N’EST PLUS satisfaite. La condition est testée même avant la première itération, et si la condition est fausse à ce moment, l’exécution se poursuit en sautant directement après la boucle, sans qu’aucune itération n’est été effectuée.

Voici un programme qui détermine à partir de quel entier i, nous avons 2 à la puissance i supérieur ou égal à 100000000:

i=0
while 2**i < 100000000:
  i = i+1
print i

Ceci est un cas typique pour lequel un for ne suffit pas et où l’on a besoin de recourir au while.

Note

  • le break peut aussi s’utiliser dans un while (comme pour un for) est permet de forcer la fin de la boucle.
  • on peut faire une boucle infinie avec le booléen True qui représente une condition toujours vraie.

L’exemple précédent peut ainsi s’écrire:

i=0
while True:
  if 2**i >= 100000000:
    break
  i = i+1
print i

Le while sert aussi à gérer les interactions avec l’utilisateur, et permet notamment de répéter un traitement tant que celui-ci le souhaite:

reponse = 'o'
while reponse <> 'n':
  x = input('Donner un nombre: ')
  print 'Son double vaut:', 2*x
  reponse = raw_input('On recommence ? (o/n): ')
print 'Ciao !'

9.2. Différences entre for et while

En dehors du fait que le while permet de faire des répétitions sans fixer a priori le nombre d’itérations, son emploi présente d’autres particularités.

A la différence du for, il faut bien penser à modifier la ou les variables qui interviennent dans la boucle. Par exemple pour afficher les nombres de 0 à 9 inclus on fera:

i = 0
while i < 10:
  print i
  i = i+1

Et non:

i = 0
while i < 10:
  print i

en effet, ici la valeur de la variable i ne change pas car il n’y a pas d’affectation qui la modifie, et la condition i < 10 sera donc toujours satisfaite, entrainant une répétition infinie de la boucle. Pour un for ce n’est pas le cas, et le programme:

for i in range(0,10):
  print i

est quant à lui correct.

Mais attention les versions du programme avec while ou avec for ne laissent pas la variable i dans le même état:

i = 0
while i < 10:
  print i
  i = i+1
print 'après la boucle, i vaut :', i

affichera pour valeur de i après la boucle: 10

Alors que:

for i in range(0,10):
  print i
print 'après la boucle, i vaut :', i

affichera pour valeur de i après la boucle: 9

9.3. Combinaisons de conditions (merci George)

Grâce à George Boole (mathématicien Britannique du XIXième), et à d’autres ... on dispose d’opérateurs algébriques sur les valeurs de vérité des conditions.

On peut obtenir la négation d’une condition à l’aide de l’opérateur not():

if not(x >= 0):
  print 'le nombre est strictement négatif'
else:
  print 'le nombre est positif ou nul'

mais aussi la disjonction de deux conditions (c’est à dire en fait un OU) à l’aide de l’opérateur or:

if (x > 0) or (x==0):
  print 'le nombre est positif ou nul'
else:
  print 'le nombre est strictement négatif'

et enfin la conjonction de deux conditions (un ET) avec l’opérateur and:

if (x > 0) and (y > 0):
  print 'les deux nombres sont strictement positifs'
else:
  print "au moins un des deux nombres n'est pas strictement positif"

Tout ce joli monde peut se composer, à chacun de choisir ces formes préférées. Ici un not() et un or:

if not((x > 0) or (x==0)):
  print 'le nombre est strictement négatif'
else:
  print 'le nombre est positif ou nul'

Là un not(), un or et un and:

if not((x < 0) or (x==0)) and (y > x):
  print 'x est strictement positif et y est strictement plus grand que x'
else:
  print "x n'est pas strictement positif, ou y n'est pas strictement plus grand que x"

Note

Bien sûr not(), and et or peuvent s’employer partout où des conditions sont utilisées, notamment dans les boucles while. Voici un exemple d’utilisation pour un contrôle de saisie:

x = 0 # pour pouvoir entrer dans la boucle
y = 0

while not( (x > 0) and ((y < 0) or (y > x)) ):
  x = input('Donner un nombre x strictement positif')
  y = input('Donner un nombre y strictement négatif ou strictement plus grand que x:')

Une condition peut prendre deux valeurs:

  • la valeur vrai notée True
  • la valeur faux notée False

Ces deux valeurs forment le domaine du type appelé type booléen. Elles peuvent être stockées dans des variables et utilisées comme paramètres ou résultats de fonctions, tout comme des entiers ou des flottants. Avoir recours à des variables contenant des valeurs de type booléen est souvent une façon de faciliter l’écriture d’un programme, et aussi de le rendre plus lisible. Par exemple, en utilisant une variable booléenne, le code de contrôle de saisie précédent peut s’écrire:

saisieOk = False

while not(saisieOk):
  x = input('Donner un nombre x strictement positif')
  y = input('Donner un nombre y strictement négatif ou strictement plus grand que x:')
  saisieOk = (x > 0) and ( (y < 0) or (y > x) )

Warning

En algèbre de Boole il existe une règle de priorité entre les opérateurs, tout comme en algèbre classique, où * et prioritaire sur +. Ici c’est and qui est prioritaire sur or. Toutefois, afin de faciliter la lecture des programmes et réduire les causes d’erreurs, il est fortement recommandé de ne pas se reposer sur cette règle, et d’utiliser systématiquement des parenthèses, comme cela a été fait dans les exemples donnés dans cette section.