Le with
l'instruction remplace l'ancien try...finally
blocs en Python. Il garantit que le code de nettoyage est exécuté. Par exemple, il ferme les fichiers ouverts avant de quitter le bloc. Considérez cet exemple de code (en supposant que ce code est stocké dans un fichier nommé 'code.py'
):
with open('code.py') as code: print(code.read())
La sortie de ce code serait le code lui-même (pour les nerds :un morceau de code qui se génère lui-même s'appelle un Quine ):
''' OUTPUT with open('code.py') as code: print(code.read()) '''
Peu importe ce qui ne va pas dans le with
block, Python fermera le fichier ouvert avant de continuer dans le code. De cette façon, vous n'avez pas besoin d'entourer le code d'un try...except
déclaration.
Expression unique "avec" sur une seule ligne
Problème :Pouvez-vous écrire le with
déclaration en une seule ligne de code ?
Solution :Oui, vous pouvez écrire le with
instruction en une seule ligne de code si le corps de la boucle ne comporte qu'une seule instruction :
with open('code.py') as code: print(code.read())
En général, vous pouvez écrire n'importe quel bloc d'indentation (comme if
déclarations, with
environnements, ou while
loops) dans une seule ligne de code si le corps se compose d'une seule instruction.
Exercice :Le code interactif suivant renvoie une erreur si vous l'exécutez. Corrigez le bogue et exécutez le bon code !
Instruction "avec" multi-expressions sur une seule ligne
Si le corps est composé de plusieurs déclarations, vous pouvez utiliser un point-virgule entre les différentes déclarations :
with open('code.py') as code: print('The code:') print(code.read())
Le bloc de code précédent devient :
with open('code.py') as code: print('The code:'); print(code.read())
Notez que dans ce cas particulier, la sémantique change en fait car le code lit son propre fichier source ! Mais dans tous les autres cas, la sémantique reste la même.
Dès que vous avez des blocs imbriqués comme un for
boucle à l'intérieur d'un with
block, vous ne pouvez plus utiliser cette approche car le code deviendrait ambigu. Croyez-le ou non, mais l'indentation sert un véritable objectif en Python ! 😉
Blocs d'indentation imbriqués dans une instruction « avec » sur une ligne
Si vous connaissez les tutos Finxter, vous savez aussi que je conclus rarement par une telle affirmation "XYZ is impossible" car dans la plupart des cas, ce n'est pas le cas. Si vous ne savez pas si vous pouvez compresser un algorithme en une seule ligne de code, ne le faites pas. Vous pouvez compresser tous les algorithmes en une seule ligne !
Dans la plupart des cas, vous pouvez éviter les blocs imbriqués en utilisant la compréhension de liste (plutôt qu'un for
boucle) ou l'opérateur ternaire (plutôt qu'un if
bloquer).
Considérez l'exemple suivant avec un for
boucle à l'intérieur d'un with
bloquer :
with open('code.py') as code: for i in range(10): print(code.read())
Problème :One-Linerize un bloc avec imbriqué !
Mauvaise solution :Écrivez-le sur une seule ligne :
Solution correcte :Remplacez la boucle for interne par une instruction de compréhension de liste !
with open('code.py') as code: [print(code.read()) for i in range(10)]
Pendant que ce code s'exécute et résout le problème, veuillez noter que l'exemple choisi n'a pas beaucoup de sens. Le fichier n'est lu qu'une seule fois, même si vous le placez dans une boucle for. La raison en est que le lecteur de fichier a fini de lire le fichier après la première itération. Dans les itérations suivantes, il ne lit que les caractères restants (il n'y en a pas) donc la sortie n'est pas 10x seulement 1x le contenu du fichier.