De nombreuses instructions ont été volontairement écartées de Python. Le goto
bien entendu, mais aussi le switch
, unless
et le do...while
.
Le but est de limiter le nombre de mots clés à connaitre afin de comprendre le langage. Les créateurs ont choisi donc de mettre de côté des mots clés trop souvent mal utilisés, pas assez utilisés, ou qui possèdent des alternatives suffisantes.
La boucle while
est rarement utilisée en Python, en tout cas beaucoup, beaucoup moins que sa petite soeur la boucle for
. Avoir besoin d’un do...while
est encore plus rare, et donc ne peut faire partie du club très fermé des mots clés réservés.
Si l’on souhaite obtenir l’effet du do..while
en python, on fait donc généralement une boucle infinie suivie d’un break sur une condition. Exemple:
import random choix = random.randint(0, 100) while True: reponse = int(input('Devinez le nombre: ')) if reponse < choix: print('Plus grand') elif reponse > choix: print('Plus petit') else: break print('Bravo') |
Le défaut de cette technique est qu’elle ne rend pas clair dès le début la condition de sortie de la boucle. Aujourd’hui en parcourant la mailling list python-idea, je suis tombé sur une idée pas conne:
import random choix = random.randint(0, 100) while "L'utilisateur n'a pas encore deviné le nombre": reponse = int(input('Devinez le nombre: ')) if reponse < choix: print('Plus grand') elif reponse > choix: print('Plus petit') else: break print('Bravo') |
Ca marche car les chaînes non vides sont toujours vraies en Python, et ça documente le code :)
Ça marche, mais ça va pas apporter de la confusion? La conversion en booléan des différents types est pas forcément super connu j’ai l’impression..
Il n’y a pas de conversion en booléen, mais toutes les valeurs Python ont une valeur dans un contexte de logique booléenne. Cela fait partie de la base de connaissance du langage. On peut bien entendu ne pas le savoir. On a tous le droit d’être débutant, mais on ne peut pas demander d’utiliser le langage uniquement partiellement pour que les débutant comprennent toujours tout.
Perso j’ai plutôt tendance à faire ca en fait :
import random
choix = random.randint(0, 100)
reponse = None
while reponse != choix:
reponse = int(input('Devinez le nombre: '))
if reponse < choix:
print('Plus grand')
elif reponse > choix:
print('Plus petit')
print('Bravo')
Ca a l’avantage d’être explicite et concis, pas besoin de break (ce qui peut être un avantage en cas de récursion multiple) et facile à comprendre pour tous.
A l’inverse je préfère les boucles infinies avec
break
quand les conditions d’arrêt ne sont pas super simples (genre arrêter en cas d’une exemption particulière par exemple).Je ne vois que peu de cas d’usage de
do ... while
qui ne sont pas remplacables par un exemple comme le mien.Le match de Rust serait interessant à pythoniser.
println!(“Tell me about {}”, number);
match number {
// Match a single value
1 => println!(“One!”),
https://rustbyexample.com/flow_control/match.html
Ça me rappelle un échange récent entre Hettinger et Beazley, la premier ayant fini par proposer, taquin, l’utilisation de :
while "False":
Sur le principe je trouve ça fun, mais en même temps je trouve que c’est un peu détourner la propriété des chaînes non vides à être toujours vraie. Ça ne me semble pas très explicite.
Dans le premier exemple, la ligne :
choix = random.randint(0, 1)
Ce ne serait pas plutôt
randint(0, 100)
?Une typo : “Le défaut de cette technique et qu’elle” -> “Le défaut de cette technique est qu’elle”
@dineptus: je suis assez d’accord. C’est plus une réponse à une question qu’on me pose souvent.
@buffalo974:
On ne gagne pas grand chose. Une syntaxe spéciale pour faire ce qu’on peut déjà aire avec des builts in, c’est un peu overkill:
@Alerion : oui :)
@Abjects : anéfé
Hum, il y a bien une évaluation Vrai/Faux de la chaîne donc un transtypage (c’est un des pièges de Python que je regrette pour les débutants, on voit écrire dans certains exercices:
if v == ('o' or 'n')
).Dans ce cas je préfère un
while True:
, pour lequel tout développeur doit se dire qu’il y aura unbreak
dans le corps de la boucle.Ou sinon quelque chose comme:
continuer = True
while continuer:
… blabla
continuer = expression qu'on mettrais dans le do while
D’ailleurs, ça peut facilement s’adapter en répéter jusqu’à.
J’utilise toujours la méthode de dineptus (comme lui, j’évite le
break
pour les cas simples). Pour ledo ... until...
, on fait::continuer = True
while continuer:
. . . . contenu de la boucle
. . . . continuer = not(condition d'arrêt)
sortie de boucle
Question un peu HS mais il y aurait pas moyen d’activer markdown au lieu de HTML pour les commentaires ? A chaque fois j’oublie d’ajouter
pre
avant decode
et la mise en page se casse :(Je pourrais aussi mieux regarder la preview à la place donc c’est en grande partie ma faute j’en suis conscient, et désolé ;)
@Laurent Pointal : pas de transtypage, car il n’y a pas de conversion de type. C’est du duck typing. On peut l’implémenter soit même en créant une méthode bool sur ses objets.
@dineptus : faudrait rajouter un plugin wordpress mais c’est sans doute possible.
Personnellement, je n’aime pas du tout cette pratique, j’ai tendance à éviter le
break
autant que possible car ça oblige à refaire globalement l’algorithme du bloc dans sa tête pour comprendre le fonctionnement, et puis ce n’est pas joli syntaxiquement. Je préfère la version où la condition de boucle a un sens logique. Sinon je me sers souvent d’un truc de Python qui ne sert à rien mais qui indique “humainement” ce que je veux faire lorsque je fais une boucle do…while, c’est Ellipsis (qui vaut True en valeur booléenne).data = ...
while data:
url = r'{base_url}?page={page}'
data = session.get(url).json()
for element in data:
do_something(element)
page += 1
@SAM
Sur le transtypage,
Désassemblé:
Il n’y a pas de récupération de la valeur booléenne, mais une évaluation de la valeur en tant que booléen… est-ce que ça peut être considéré comme un transtypage (implicite) ou non…
Respect pour le désassemblage.
Attention, scoop : Python permet de commenter le code ! ;-)
while True: # L'utilisateur n'a pas encore deviné le nombre
;)
@OPi: Dans ce cas là il faut 2 espaces avant le # pour les commentaires en fin de ligne. pep8 rocks ! :D
Quand j’ai vu ce post, j’ai fini par me dire que si personne n’a benché j’allais le faire.
Je vous propose ce code pour tester qui selon moi fait l’affaire, mais j’ai pu négliger quelque chose
Les résultats me surprennent. Chez moi le test booleen prend plus de temps et ce n’est pas négligeable. Par ailleurs entre python 2.7 et 3.5 il y a aussi de gros écarts : ~ +60% de temps pour python 3.
Heureusement, je ne fais pas tous les jours des boucles de while.
Pareil. Surprenant.
Sinon :
first = true
while first or xxx :
first = false
#code