Cours Python en ligne
Si vous êtes comme la plupart des utilisateurs de Python, y compris moi, vous avez probablement commencé votre aventure avec Python en apprenant: impression()
. Cela vous a aidé à écrire votre propre Bonjour le monde
bon mot. Vous pouvez l'utiliser pour afficher des messages formatés à l'écran et peut-être trouver des bugs. Mais si vous pensez que tout ce qu'il y a à savoir sur le fonctionnement de Python impression()
fonction, alors vous manquez beaucoup!
Continuez votre lecture pour profiter pleinement de cette petite fonction apparemment ennuyeuse et méconnue. Ce tutoriel vous familiarisera avec l’utilisation de Python impression()
efficacement. Cependant, préparez-vous pour une plongée profonde en parcourant les sections. Vous pourriez être surpris combien impression()
a à offrir!
À la fin de ce tutoriel, vous saurez comment:
- Évitez les erreurs courantes avec Python
impression()
- Traiter les nouvelles lignes, les encodages de caractères et la mise en mémoire tampon
- Écrire du texte dans des fichiers
- Moquer
impression()
en tests unitaires - Construire des interfaces utilisateur avancées dans le terminal
Si vous êtes un débutant complet, vous tirerez le meilleur parti de la lecture de la première partie de ce didacticiel, qui illustre l’essentiel de l’impression en Python. Sinon, n'hésitez pas à sauter cette partie et à vous déplacer comme bon vous semble.
Remarque: impression()
était un ajout majeur à Python 3, dans lequel il remplaçait l'ancien impression
déclaration disponible en Python 2.
Il y a plusieurs bonnes raisons à cela, comme vous le verrez bientôt. Bien que ce tutoriel se concentre sur Python 3, il montre l'ancienne méthode d'impression en Python pour référence.
Imprimer en quelques mots
Voyons quelques exemples concrets d’impression en Python. À la fin de cette section, vous connaîtrez tous les moyens possibles pour appeler impression()
. Ou, dans le jargon des programmeurs, vous diriez que vous serez familiarisé avec le signature de fonction.
Appel d'impression
L'exemple le plus simple d'utilisation de Python impression()
nécessite seulement quelques frappes:
Vous ne transmettez aucun argument, mais vous devez toujours mettre des parenthèses vides à la fin, qui indiquent à Python d’exécuter la fonction plutôt que de simplement y faire référence par son nom.
Cela produira un caractère de nouvelle ligne invisible, ce qui provoquera l'apparition d'une ligne vierge sur votre écran. Tu peux appeler impression()
plusieurs fois comme celui-ci pour ajouter de l'espace vertical. C’est comme si tu frappais Entrer sur votre clavier dans un traitement de texte.
UNE caractère de nouvelle ligne est un caractère de contrôle spécial utilisé pour indiquer la fin d'une ligne (EOL). Il n’a généralement pas de représentation visible à l’écran, mais certains éditeurs de texte peuvent afficher de tels caractères non imprimables avec peu de graphiques.
Le mot "caractère" est un peu impropre dans ce cas, car une nouvelle ligne est souvent longue de plus d'un caractère. Par exemple, le système d'exploitation Windows, ainsi que le protocole HTTP, représentent des nouvelles lignes avec une paire de caractères. Parfois, vous devez tenir compte de ces différences pour concevoir des programmes réellement portables.
Pour savoir ce qui constitue une nouvelle ligne dans votre système d’exploitation, utilisez la commande intégrée de Python. os
module.
Cela vous dira immédiatement que les fenêtres et DOS représenter la nouvelle ligne comme une séquence de r
suivi par n
:
>>> importation os
>>> os.lineep
' r n'
Sur Unix, Linux, et les versions récentes de macOS, c’est un n
personnage:
>>> importation os
>>> os.lineep
' n'
Le classique Mac OS Xreste cependant fidèle à sa philosophie "penser différemment" en choisissant une autre représentation:
>>> importation os
>>> os.lineep
' r'
Remarquez comment ces caractères apparaissent dans les littéraux de chaîne. Ils utilisent une syntaxe spéciale avec une barre oblique inverse précédente () pour indiquer le début d'un séquence de caractères d'échappement. De telles séquences permettent de représenter des caractères de contrôle, qui seraient autrement invisibles à l'écran.
La plupart des langages de programmation sont livrés avec un ensemble prédéfini de séquences d'échappement pour des caractères spéciaux tels que:
\
: barre oblique inverseb
: retour arrièret
: languetter
: retour chariot (CR)n
: newline, également appelé saut de ligne (LF)
Les deux dernières rappellent les machines à écrire mécaniques, qui nécessitaient deux commandes distinctes pour insérer une nouvelle ligne. La première commande ramènerait le chariot au début de la ligne actuelle, tandis que la seconde ferait avancer le rouleau jusqu'à la ligne suivante.
En comparant le correspondant Codes de caractères ASCIIvous verrez que le fait de mettre une barre oblique inverse devant un personnage change complètement sa signification. Cependant, tous les personnages ne le permettent pas – seulement les spéciaux.
Pour comparer les codes de caractères ASCII, vous pouvez utiliser le logiciel intégré. ord ()
une fonction:
>>> ord('r')
114
>>> ord(' r')
13
Gardez à l'esprit que, pour former une séquence d'échappement correcte, il ne doit pas y avoir d'espace entre la barre oblique inverse et une lettre!
Comme vous venez de le voir, en appelant impression()
sans argument aboutit à un ligne blanche, qui est une ligne composée uniquement du caractère newline. Ne confondez pas cela avec un ligne vide, qui ne contient aucun caractère, pas même la nouvelle ligne!
Vous pouvez utiliser les littéraux de chaîne de Python pour visualiser ces deux éléments:
' n' # Ligne blanche
'' # Ligne vide
Le premier est long d'un caractère, tandis que le second n'a pas de contenu.
Remarque: Pour supprimer le caractère de nouvelle ligne d’une chaîne en Python, utilisez son .rstrip ()
méthode, comme ceci:
>>> 'Une ligne de texte. n'.bande de retour()
'Une ligne de texte.'
Cela supprime les espaces finaux du bord droit de la chaîne de caractères.
Dans un scénario plus courant, vous souhaitez communiquer un message à l’utilisateur final. Il y a plusieurs façons d'y parvenir.
Tout d'abord, vous pouvez passer un littéral de chaîne directement à impression()
:
>>> impression('Veuillez patienter pendant le chargement du programme ...')
Cela imprimera le message textuellement sur l'écran.
Littéraux de chaîne en Python peuvent être entre guillemets simples ('
) ou des guillemets doubles ("
). Selon le guide de style officiel de PEP 8, vous devriez en choisir un et continuer à l’utiliser de manière constante. Il n’ya pas de différence, sauf si vous devez imbriquer un dans un autre.
Par exemple, vous ne pouvez pas utiliser de guillemets doubles pour le littéral et également inclure des guillemets doubles à l'intérieur, car cela est ambigu pour l'interpréteur Python:
"Mon livre favori est "Python Des trucs"" # Faux!
Ce que vous voulez faire, c'est mettre le texte qui contient des guillemets doubles entre guillemets simples:
"Mon livre préféré est" Python Tricks ""
Le même truc fonctionnerait dans l'autre sens:
"Mon livre préféré est" Les astuces en python ""
Vous pouvez également utiliser les séquences de caractères d'échappement mentionnées précédemment pour que Python traite ces doubles guillemets internes littéralement comme faisant partie du littéral de chaîne:
"Mon livre favori est "Astuces de python ""
S'échapper, c'est bien, mais cela peut parfois gêner. Plus précisément, lorsque vous avez besoin que votre chaîne contienne un nombre relativement élevé de caractères de barre oblique inverse sous forme littérale.
Un exemple classique est un chemin de fichier sous Windows:
'C: Utilisateurs jdoe' # Faux!
'C:\Utilisateurs\jdoe '
Notez que chaque caractère de barre oblique inverse doit être échappé avec une autre barre oblique inverse.
Ceci est encore plus évident avec les expressions régulières, qui sont rapidement compliquées à cause de l'utilisation intensive de caractères spéciaux:
'^\w:\\(? :(? :( ?:[^[^[^[^\\]+)? | (? ?:[^[^[^[^\\]+)\\[^[^[^[^\\]+) *) $ '
Heureusement, vous pouvez désactiver complètement l'échappement du personnage à l'aide de littéraux de chaîne brute. Simplement ajouter un r
ou R
avant la citation d'ouverture, et maintenant vous vous retrouvez avec ceci:
r'C: Utilisateurs jdoe'
r'^ w:\(? :(? :( ?:[^[^[^[^\]+)? | (? ?:[^[^[^[^\]+)\[^[^[^[^\]+) *) $ '
C’est beaucoup mieux, n’est-ce pas?
Il existe quelques autres préfixes qui donnent une signification particulière aux littéraux de chaîne en Python, mais vous ne les expliquerez pas ici.
Enfin, vous pouvez définir des littéraux de plusieurs lignes en les entourant '' '
ou "" "
, qui sont souvent utilisés comme docstrings.
Voici un exemple:
"" "
Ceci est un exemple
d'une chaîne multiligne
en Python.
"" "
Pour éviter une nouvelle ligne initiale, il suffit de mettre le texte juste après l'ouverture "" "
:
"""Ceci est un exemple
d'une chaîne multiligne
en Python.
"" "
Vous pouvez également utiliser une barre oblique inverse pour vous débarrasser de la nouvelle ligne:
"" "
Ceci est un exemple
d'une chaîne multiligne
en Python.
"" "
Pour supprimer l’indentation d’une chaîne multiligne, vous pouvez tirer parti des fonctions intégrées. habillage de texte
module:
>>> importation habillage de texte
>>> paragraphe = '' '
... Ceci est un exemple
... d'une chaîne multiligne
... en Python.
... '' '
...
>>> impression(paragraphe)
Ceci est un exemple
d'une chaîne multiligne
en Python.
>>> impression(habillage de texte.déduction(paragraphe).bande())
Ceci est un exemple
d'une chaîne multiligne
en Python.
Cela prendra soin des paragraphes non-indenting pour vous. Il existe également quelques autres fonctions utiles dans habillage de texte
pour l’alignement du texte, vous le trouverez dans un traitement de texte.
Deuxièmement, vous pouvez extraire ce message dans sa propre variable avec un nom explicite pour améliorer la lisibilité et promouvoir la réutilisation du code:
>>> message = 'Veuillez patienter pendant le chargement du programme ...'
>>> impression(message)
Enfin, vous pouvez passer une expression, telle que la concaténation de chaînes, à évaluer avant d’imprimer le résultat:
>>> importation os
>>> impression('Bonjour, ' + os.getlogin() + '! Comment vas-tu?')
Bonjour jdoe! Comment vas-tu?
En fait, il existe une douzaine de façons de formater les messages en Python. Je vous encourage vivement à consulter les chaînes de caractères f, introduites dans Python 3.6, car elles offrent la syntaxe la plus concise:
>>> importation os
>>> impression(F'Bonjour, os.getlogin ()! Comment vas-tu?')
De plus, les f-strings vous éviteront de commettre une erreur commune, qui consiste à oublier de taper des opérandes concaténés. Python est un langage fortement typé, ce qui signifie qu’il ne vous permettra pas de faire ceci:
>>> 'Mon âge est ' + 42
Traceback (dernier appel le plus récent):
Fichier "", ligne 1, dans
'Mon âge est ' + 42
Erreur-type: ne peut que concaténer str (pas "int") à str
C’est faux car l’ajout de nombres à des chaînes n’a pas de sens. Vous devez d'abord convertir explicitement le nombre en chaîne, afin de les réunir:
>>> 'Mon âge est ' + str(42)
'Mon âge a 42 ans'
Sauf si vous gérez vous-même de telles erreurs, l'interpréteur Python vous informera d'un problème en affichant une trace.
Remarque: str ()
est une fonction intégrée globale qui convertit un objet en sa représentation sous forme de chaîne.
Vous pouvez l'appeler directement sur n'importe quel objet, par exemple un nombre:
Les types de données intégrés ont une représentation prédéfinie sous forme de chaîne, mais plus loin dans cet article, vous découvrirez comment en fournir une pour vos classes personnalisées.
Comme pour toute fonction, peu importe que vous passiez un littéral, une variable ou une expression. Contrairement à beaucoup d'autres fonctions, cependant, impression()
acceptera n'importe quoi, peu importe son type.
Jusqu'ici, vous avez seulement regardé la chaîne, mais qu'en est-il des autres types de données? Essayons des littéraux de différents types intégrés et voyons ce qui en sort:
>>> impression(42) #
42
>>> impression(3.14) #
3.14
>>> impression(1 + 2j) #
(1 + 2j)
>>> impression(Vrai) #
Vrai
>>> impression([[[[1, 2, 3]) #
[1, 2, 3]
>>> impression((1, 2, 3)) #
(1, 2, 3)
>>> impression('rouge', 'vert', 'bleu') #
'rouge', 'vert', 'bleu'
>>> impression('prénom': 'Alice', 'âge': 42) #
'name': 'Alice', 'age': 42
>>> impression('Bonjour') #
Bonjour
Attention au Aucun
constante, cependant. Bien qu’il soit utilisé pour indiquer l’absence d’une valeur, celle-ci apparaîtra comme 'Aucun'
plutôt qu'une chaîne vide:
Comment impression()
savoir comment travailler avec tous ces types différents? Eh bien, la réponse courte est que ce n’est pas le cas. Il appelle implicitement str ()
dans les coulisses pour taper jeté n'importe quel objet dans une chaîne. Ensuite, il traite les cordes de manière uniforme.
Dans la suite de ce didacticiel, vous apprendrez à utiliser ce mécanisme pour imprimer des types de données personnalisés tels que vos classes.
Ok, vous pouvez maintenant appeler impression()
avec un seul argument ou sans aucun argument. Vous savez comment imprimer des messages fixes ou formatés à l'écran. La prochaine sous-section développera un peu la mise en forme des messages.
Pour obtenir le même résultat lors de la génération de langue précédente, vous souhaiterez normalement supprimer les parenthèses entourant le texte:
# Python 2
impression
impression 'S'il vous plaît, attendez...'
impression 'Bonjour, % s! Comment vas-tu?' % os.getlogin()
impression 'Bonjour, % s. Ton âge est %ré' % (prénom, âge)
C'est parce que impression
n'était pas une fonction à l'époque, comme vous le verrez dans la section suivante. Notez toutefois que, dans certains cas, les parenthèses en Python sont redondantes. Il ne serait pas nocif de les inclure car ils seraient simplement ignorés. Est-ce que cela signifie que vous devriez utiliser le impression
déclaration comme si c'était une fonction? Absolument pas!
Par exemple, les parenthèses entourant une seule expression ou un littéral sont facultatives. Les deux instructions produisent le même résultat dans Python 2:
>>> # Python 2
>>> impression 'S'il vous plaît, attendez...'
S'il vous plaît, attendez...
>>> impression('S'il vous plaît, attendez...')
S'il vous plaît, attendez...
Les crochets font en réalité partie de l’expression plutôt que du impression
déclaration. Si votre expression ne contient qu’un seul élément, c’est comme si vous n’aviez pas inclus les crochets du tout.
D'autre part, mettre des parenthèses autour de plusieurs éléments forme un tuple:
>>> # Python 2
>>> impression 'Mon nom est', 'John'
Mon nom est John
>>> impression('Mon nom est', 'John')
('Mon nom est John')
C'est une source connue de confusion. En fait, vous obtiendriez également un tuple en ajoutant une virgule de fin au seul élément entouré de parenthèses:
>>> # Python 2
>>> impression('S'il vous plaît, attendez...')
S'il vous plaît, attendez...
>>> impression('S'il vous plaît, attendez...',) # Remarquez la virgule
('S'il vous plaît, attendez...',)
L’essentiel est que vous ne devriez pas appeler impression
entre parenthèses en Python 2. Bien que, pour être tout à fait exact, vous pouvez contourner ce problème à l’aide d’un __futur__
import, que vous lirez plus en détail dans la section correspondante.
Séparer plusieurs arguments
Vous avez vu impression()
appelé sans aucun argument pour produire une ligne vide, puis avec un seul argument pour afficher un message fixe ou formaté.
Cependant, il s’avère que cette fonction peut accepter n’importe quel nombre de arguments de position, y compris zéro, un ou plusieurs arguments. C’est très pratique dans un cas courant de formatage de message, dans lequel vous voudriez joindre quelques éléments.
Les arguments peuvent être passés à une fonction de plusieurs façons. Une façon est de nommer explicitement les arguments lorsque vous appelez la fonction, comme ceci:
>>> def div(une, b):
... revenir une / b
...
>>> div(une=3, b=4)
0,75
Comme les arguments peuvent être identifiés par leur nom, leur ordre n’a pas d’importance. Les échanger donnera toujours le même résultat:
>>> div(b=4, une=3)
0,75
Inversement, les arguments passés sans nom sont identifiés par leur position. C'est pourquoi arguments de position respecter scrupuleusement l'ordre imposé par la signature de la fonction:
>>> div(3, 4)
0,75
>>> div(4, 3)
1.3333333333333333
impression()
permet un nombre arbitraire d'arguments de position grâce à la * args
paramètre.
Voyons cet exemple:
>>> importation os
>>> impression('Mon nom est', os.getlogin(), 'et je suis', 42)
Je m'appelle jdoe et j'ai 42 ans
impression()
a concaténé les quatre arguments qui lui ont été transmis, et il a inséré un seul espace entre eux afin que vous ne vous retrouviez pas avec un message écrasé comme 'Je m'appelle et je suis42'
.
Notez qu’il s’est également occupé du bon typage en appelant implicitement str ()
sur chaque argument avant de les rejoindre. Si vous vous souvenez de la sous-section précédente, une concaténation naïve peut facilement entraîner une erreur en raison de types incompatibles:
>>> impression('Mon âge est: ' + 42)
Traceback (dernier appel le plus récent):
Fichier "", ligne 1, dans
impression('Mon âge est: ' + 42)
Erreur-type: ne peut que concaténer str (pas "int") à str
En plus d'accepter un nombre variable d'arguments de position, impression()
définit quatre nommés ou arguments de mots clés, qui sont optionnels car ils ont tous des valeurs par défaut. Vous pouvez consulter leur brève documentation en appelant aide (imprimer)
de l'interprète interactif.
Concentrons-nous sur SEP
juste pour le moment. Ça signifie séparateur et se voit attribuer un seul espace (''
) par défaut. Il détermine la valeur pour joindre des éléments.
Ce doit être soit une chaîne ou Aucun
, mais ce dernier a le même effet que l'espace par défaut:
>>> impression('Bonjour', 'monde', SEP=Aucun)
Bonjour le monde
>>> impression('Bonjour', 'monde', SEP='')
Bonjour le monde
>>> impression('Bonjour', 'monde')
Bonjour le monde
Si vous voulez supprimer complètement le séparateur, vous devez passer une chaîne vide (''
) au lieu:
>>> impression('Bonjour', 'monde', SEP='')
Bonjour le monde
Vous voudrez peut-être impression()
pour joindre ses arguments en tant que lignes séparées. Dans ce cas, passez simplement le caractère de nouvelle ligne échappé décrit plus haut:
>>> impression('Bonjour', 'monde', SEP=' n')
Bonjour
monde
Un exemple plus utile de la SEP
paramètre serait l'impression quelque chose comme les chemins de fichiers:
>>> impression('maison', 'utilisateur', 'documents', SEP='/')
accueil / utilisateur / documents
Rappelez-vous que le séparateur se situe entre les éléments, pas autour d'eux, vous devez donc en rendre compte d'une manière ou d'une autre:
>>> impression('/maison', 'utilisateur', 'documents', SEP='/')
/ home / utilisateur / documents
>>> impression('', 'maison', 'utilisateur', 'documents', SEP='/')
/ home / utilisateur / documents
Plus précisément, vous pouvez insérer un caractère barre oblique (/
) dans le premier argument de position, ou utilisez une chaîne vide comme premier argument pour appliquer la barre oblique.
Remarque: Faites attention à joindre des éléments d'une liste ou d'un tuple.
Le faire manuellement aura comme conséquence un bien connu Erreur-type
si au moins un des éléments n’est pas une chaîne:
>>> impression(''.joindre([[[['jdoe is', 42, 'ans']))
Traceback (dernier appel le plus récent):
Fichier "", ligne 1, dans
impression(','.joindre([[[['jdoe is', 42, 'ans']))
Erreur-type: séquence élément 1: instance attendue str, int trouvé
Il est plus sûr de déballer la séquence avec l’opérateur en étoile (*
) et laisser impression()
type de poignée coulée:
>>> impression(*[[[['jdoe is', 42, 'ans'])
jdoe a 42 ans
Décompresser équivaut effectivement à appeler impression()
avec des éléments individuels de la liste.
Un autre exemple intéressant pourrait être l’exportation de données au format CSV (valeurs séparées par des virgules):
>>> impression(1, «Tours de python», Dan Bader, SEP=',')
1, astuces de python, Dan Bader
Cela ne gèrerait pas les cas extrêmes tels que les virgules, mais cela devrait être le cas pour les cas d'utilisation simples. La ligne ci-dessus apparaît dans la fenêtre de votre terminal. Pour le sauvegarder dans un fichier, vous devez rediriger la sortie. Plus loin dans cette section, vous verrez comment utiliser impression()
écrire du texte dans des fichiers directement à partir de Python.
Finalement, le SEP
Ce paramètre n’est pas limité à un seul caractère. Vous pouvez joindre des éléments avec des chaînes de n'importe quelle longueur:
>>> impression('nœud', 'enfant', 'enfant', SEP='->')
noeud -> enfant -> enfant
Dans les sous-sections à venir, vous explorerez les autres arguments de mot-clé du impression()
une fonction.
Pour imprimer plusieurs éléments dans Python 2, vous devez placer les parenthèses autour d'eux, comme auparavant:
>>> # Python 2
>>> importation os
>>> impression 'Mon nom est', os.getlogin(), 'et je suis', 42
Je m'appelle jdoe et j'ai 42 ans
Si vous les gardiez, par contre, vous ne feriez passer qu’un seul tuple à la impression
déclaration:
>>> # Python 2
>>> importation os
>>> impression('Mon nom est', os.getlogin(), 'et je suis', 42)
('Mon nom est', 'jdoe', 'et je suis', 42)
De plus, il n’ya aucun moyen de modifier le séparateur par défaut des éléments joints dans Python 2, aussi une solution de contournement consiste à utiliser une interpolation de chaîne comme ceci:
>>> # Python 2
>>> importation os
>>> impression 'Mon nom est % s et je suis %ré' % (os.getlogin(), 42)
Je m'appelle jdoe et j'ai 42 ans
C’était le moyen par défaut de formater les chaînes jusqu’à ce que le .format()
La méthode a été rétroportée depuis Python 3.
Prévenir les sauts de ligne
Parfois, vous ne souhaitez pas mettre fin à votre message avec une fin de ligne, de sorte que les appels ultérieurs à impression()
continuera sur la même ligne. Les exemples classiques incluent la mise à jour de la progression d'une opération de longue durée ou l'invite de l'utilisateur à entrer. Dans ce dernier cas, vous voulez que l'utilisateur tape la réponse sur la même ligne:
Es-tu sûr de vouloir faire ça? [y/n] y
De nombreux langages de programmation exposent des fonctions similaires à impression()
via leurs bibliothèques standard, mais ils vous laissent décider d’ajouter ou non une nouvelle ligne. Par exemple, en Java et en C #, vous avez deux fonctions distinctes, alors que dans d’autres langages, vous devez ajouter explicitement n
à la fin d'un littéral de chaîne.
Voici quelques exemples de syntaxe dans de tels langages:
La langue | Exemple |
---|---|
Perl | print "bonjour le monde n" |
C | printf ("bonjour le monde n"); |
C ++ | std :: cout << "bonjour le monde" << std :: endl; |
En revanche, Python impression()
la fonction ajoute toujours n
sans demander, car c’est ce que vous voulez dans la plupart des cas. Pour le désactiver, vous pouvez utiliser un autre argument de mot clé, fin
, qui dicte avec quoi terminer la ligne.
En termes de sémantique, le fin
paramètre est presque identique à la SEP
celui que vous avez vu plus tôt:
- Ce doit être une chaîne ou
Aucun
. - Cela peut être arbitrairement long.
- Il a une valeur par défaut de
' n'
. - Si égal à
Aucun
, cela aura le même effet que la valeur par défaut. - Si égal à une chaîne vide (
''
), il supprimera la nouvelle ligne.
Maintenant, vous comprenez ce qui se passe sous le capot lorsque vous appelez impression()
sans argument. Etant donné que vous ne fournissez aucun argument de position à la fonction, il n’ya rien à joindre, le séparateur par défaut n’est donc pas utilisé du tout. Cependant, la valeur par défaut de fin
s'applique toujours, et une ligne vide apparaît.
Remarque: Vous vous demandez peut-être pourquoi le fin
Le paramètre a une valeur par défaut fixe plutôt que tout ce qui a du sens sur votre système d'exploitation.
Eh bien, vous n'avez pas à vous soucier de la représentation de la nouvelle ligne sous différents systèmes d'exploitation lors de l'impression, car impression()
gérera automatiquement la conversion. Rappelez-vous juste de toujours utiliser le n
séquence d'échappement dans les littéraux de chaîne.
C'est actuellement le moyen le plus portable d'imprimer un caractère de nouvelle ligne en Python:
>>> impression('ligne 1 nligne 2 nline3 ')
ligne 1
ligne 2
line3
Si vous essayez d’imprimer de manière forcée un caractère de nouvelle ligne spécifique à Windows sur une machine Linux, par exemple, vous obtiendrez une sortie cassée:
>>> impression('ligne 1 r nligne 2 r nline3 ')
line3
En revanche, lorsque vous ouvrez un fichier en lecture avec ouvrir()
, vous n’avez pas besoin de vous soucier de la représentation newline non plus. La fonction traduira toute nouvelle ligne spécifique au système rencontrée en un ' n'
. Dans le même temps, vous avez le contrôle sur la manière dont les nouvelles lignes doivent être traitées en entrée et en sortie si vous en avez vraiment besoin.
Pour désactiver la nouvelle ligne, vous devez spécifier une chaîne vide à travers le fin
argument de mot clé:
impression('Vérification de l'intégrité du fichier ...', fin='')
# (...)
impression('D'accord')
Même si ce sont deux séparés impression()
d’appels, qui peuvent s’exécuter très longtemps, vous ne verrez éventuellement plus qu’une seule ligne. Tout d’abord, cela ressemblera à ceci:
Vérification de l'intégrité du fichier ...
Cependant, après le deuxième appel à impression()
, la même ligne apparaîtra à l'écran comme suit:
Vérification de l'intégrité du fichier ... ok
Comme avec SEP
, vous pouvez utiliser fin
pour joindre des éléments individuels en une grande quantité de texte avec un séparateur personnalisé. Au lieu de joindre plusieurs arguments, il ajoute le texte de chaque appel de fonction à la même ligne:
impression("La première phrase", fin='. ')
impression("La deuxième phrase", fin='. ')
impression('La dernière phrase.')
Ces trois instructions produiront une seule ligne de texte:
La première phrase La deuxième phrase. La dernière phrase.
Vous pouvez mélanger les deux arguments de mots clés:
impression('Mercure', 'Vénus', 'Terre', SEP=',', fin=',')
impression('Mars', 'Jupiter', 'Saturne', SEP=',', fin=',')
impression('Uranus', 'Neptune', 'Pluton', SEP=',')
Non seulement vous obtenez une seule ligne de texte, mais tous les éléments sont séparés par une virgule:
Mercure, Vénus, Terre, Mars, Jupiter, Saturne, Uranus, Neptune, Pluton
Rien ne vous empêche d’utiliser le caractère de nouvelle ligne avec un rembourrage supplémentaire:
impression('Imprimer en quelques mots', fin=' n * ')
impression("Appel d'impression", fin=' n * ')
impression('Séparer plusieurs arguments', fin=' n * ')
impression("Prévenir les sauts de ligne")
Il imprimerait le texte suivant:
Imprimer en quelques mots
* Appel Imprimer
* Séparer plusieurs arguments
* Prévenir les sauts de ligne
Comme vous pouvez le voir, le fin
L'argument de mot clé acceptera des chaînes arbitraires.
Remarque: Le bouclage sur les lignes d’un fichier texte conserve ses propres caractères de nouvelle ligne, qui se combinent avec la impression()
Le comportement par défaut de la fonction donnera un caractère de nouvelle ligne redondant:
>>> avec ouvrir('fichier.txt') comme objet_fichier:
... pour ligne dans objet_fichier:
... impression(ligne)
...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
incididunt tempor ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercice ullamco laboris nisi ut aliquip ex ea commodo
Il y a deux nouvelles lignes après chaque ligne de texte. Vous souhaitez supprimer l'un d'eux, comme indiqué précédemment dans cet article, avant d'imprimer la ligne:
Alternativement, vous pouvez conserver la nouvelle ligne dans le contenu mais supprimer celle ajoutée par impression()
automatiquement Vous utiliseriez le fin
argument de mot-clé pour le faire:
>>> avec ouvrir('fichier.txt') comme objet_fichier:
... pour ligne dans objet_fichier:
... impression(ligne, fin='')
...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
incididunt tempor ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercice ullamco laboris nisi ut aliquip ex ea commodo
En terminant une ligne avec une chaîne vide, vous désactivez effectivement l'une des nouvelles lignes.
Vous vous familiarisez davantage avec l’impression en Python, mais il reste encore beaucoup d’informations utiles. Dans la prochaine sous-section, vous apprendrez à intercepter et à rediriger le impression()
sortie de la fonction.
Pour empêcher un saut de ligne dans Python 2, vous devez ajouter une virgule à la fin de l'expression:
Cependant, ce n’est pas idéal car cela ajoute aussi un espace indésirable, ce qui se traduirait par fin = ''
au lieu de fin = ''
en Python 3. Vous pouvez tester cela avec l'extrait de code suivant:
impression 'AVANT'
impression 'Bonjour',
impression 'APRÈS'
Notez qu’il y a un espace entre les mots Bonjour
et APRÈS
:
Pour obtenir le résultat attendu, vous devez utiliser l’une des astuces expliquées plus loin, à savoir importer les impression()
fonction de __futur__
ou retomber sur le sys
module:
importation sys
impression 'AVANT'
sys.stdout.écrire('Bonjour')
impression 'APRÈS'
Ceci imprimera la sortie correcte sans espace supplémentaire:
En utilisant le sys
module vous donne le contrôle sur ce qui est imprimé sur la sortie standard, le code devient un peu plus encombré.
Impression dans un fichier
Croyez-le ou non, impression()
ne sait pas comment convertir des messages en texte sur votre écran et, franchement, ce n’est pas nécessaire. C’est un travail pour les couches de code de niveau inférieur, qui comprennent les octets et savent comment les déplacer.
impression()
est une abstraction sur ces couches, fournissant une interface pratique qui délègue simplement l’impression réelle à un flux ou objet de type fichier. Un flux peut être n'importe quel fichier sur votre disque, un socket réseau ou peut-être un tampon en mémoire.
En plus de cela, il existe trois flux standard fournis par le système d'exploitation:
stdin
: entrée standardstdout
: sortie standardstderr
: erreur standard
Sortie standard Voici ce que vous voyez dans le terminal lorsque vous exécutez divers programmes en ligne de commande, y compris vos propres scripts Python:
$ chat bonjour.py
print ('Ceci apparaîtra sur stdout')
$ python bonjour.py
Cela apparaîtra sur stdout
Sauf instruction contraire, impression()
va écrire par défaut sur la sortie standard. Cependant, vous pouvez demander à votre système d’exploitation de remplacer temporairement stdout
pour un flux de fichiers, de sorte que toute sortie finisse dans ce fichier plutôt que dans l'écran:
$ python bonjour.py> fichier.txt
$ cat fichier.txt
Cela apparaîtra sur stdout
C'est ce qu'on appelle la redirection de flux.
L'erreur type est similaire à stdout
en ce sens qu'il apparaît également à l'écran. Néanmoins, il s’agit d’un flux séparé, destiné à consigner les messages d’erreur pour les diagnostics. En redirigeant l'un d'eux ou les deux, vous pouvez garder les choses propres.
Remarque: Pour rediriger stderr
, vous devez savoir sur descripteurs de fichier, aussi connu sous le nom poignées de fichier.
Ce sont des nombres arbitraires, bien que constants, associés à des flux standard. Vous trouverez ci-dessous un résumé des descripteurs de fichier pour une famille de systèmes d’exploitation compatibles POSIX:
Courant | Descripteur de fichier |
---|---|
stdin |
0 |
stdout |
1 |
stderr |
2 |
Connaître ces descripteurs vous permet de rediriger un ou plusieurs flux à la fois:
Commander | La description |
---|---|
./programme> out.txt |
Réorienter stdout |
./programme 2> err.txt |
Réorienter stderr |
./programme> out.txt 2> err.txt |
Réorienter stdout et stderr séparer les fichiers |
./program &> out_err.txt |
Réorienter stdout et stderr dans le même fichier |
Notez que >
est le même que 1>
.
Certains programmes utilisent des couleurs différentes pour distinguer les messages imprimés sur stdout
et stderr
:
Alors que les deux stdout
et stderr
sont en écriture seule, stdin
est en lecture seule. Vous pouvez considérer l’entrée standard comme votre clavier, mais comme pour les deux autres, vous pouvez permuter stdin
pour un fichier à partir duquel lire des données.
En Python, vous pouvez accéder à tous les flux standard via l’interface intégrée. sys
module:
>>> importation sys
>>> sys.stdin
<_io.TextIOWrapper name = ''mode =' r 'encoding =' UTF-8 '>
>>> sys.stdin.fileno()
0
>>> sys.stdout
<_io.TextIOWrapper name = ''mode =' w 'encoding =' UTF-8 '>
>>> sys.stdout.fileno()
1
>>> sys.stderr
<_io.TextIOWrapper name = ''mode =' w 'encoding =' UTF-8 '>
>>> sys.stderr.fileno()
2
Comme vous pouvez le constater, ces valeurs prédéfinies ressemblent à des objets de type fichier avec mode
et codage
attributs ainsi que .lis()
et .écrire()
méthodes parmi tant d’autres.
Par défaut, impression()
est lié à sys.stdout
à travers ses fichier
argument, mais vous pouvez changer cela. Utilisez cet argument de mot clé pour indiquer un fichier ouvert en mode écriture ou ajout, afin que les messages y soient directement envoyés:
avec ouvrir('file.txt', mode='w') comme file_object:
impression('hello world', fichier=file_object)
This will make your code immune to stream redirection at the operating system level, which might or might not be desired.
For more information on working with files in Python, you can check out Reading and Writing Files in Python (Guide).
Remarque: Don’t try using print()
for writing binary data as it’s only well suited for text.
Just call the binary file’s .write()
directly:
avec ouvrir('file.dat', 'wb') comme file_object:
file_object.écrire(octets(4))
file_object.écrire(b'xff')
If you wanted to write raw bytes on the standard output, then this will fail too because sys.stdout
is a character stream:
>>> importation sys
>>> sys.stdout.écrire(octets(4))
Traceback (most recent call last):
Fichier "" , line 1, dans
TypeError: write() argument must be str, not bytes
You must dig deeper to get a handle of the underlying byte stream instead:
>>> importation sys
>>> num_bytes_written = sys.stdout.tampon.écrire(b'x41x0a')
UNE
This prints an uppercase letter UNE
and a newline character, which correspond to decimal values of 65 and 10 in ASCII. However, they’re encoded using hexadecimal notation in the bytes literal.
Notez que print()
has no control over character encoding. It’s the stream’s responsibility to encode received Unicode strings into bytes correctly. In most cases, you won’t set the encoding yourself, because the default UTF-8 is what you want. If you really need to, perhaps for legacy systems, you can use the codage
argument of open()
:
avec ouvrir('file.txt', mode='w', codage='iso-8859-1') comme file_object:
impression('über naïve café', fichier=file_object)
Instead of a real file existing somewhere in your file system, you can provide a fake one, which would reside in your computer’s memory. You’ll use this technique later for mocking print()
in unit tests:
>>> importation io
>>> fake_file = io.StringIO()
>>> impression('hello world', fichier=fake_file)
>>> fake_file.getvalue()
'hello worldn'
If you got to this point, then you’re left with only one keyword argument in print()
, which you’ll see in the next subsection. It’s probably the least used of them all. Nevertheless, there are times when it’s absolutely necessary.
There’s a special syntax in Python 2 for replacing the default sys.stdout
with a custom file in the impression
statement:
avec ouvrir('file.txt', mode='w') comme file_object:
impression >> file_object, 'hello world'
Because strings and bytes are represented with the same str
type in Python 2, the impression
statement can handle binary data just fine:
avec ouvrir('file.dat', mode='wb') comme file_object:
impression >> file_object, 'x41x0a'
Although, there’s a problem with character encoding. le open()
function in Python 2 lacks the codage
parameter, which would often result in the dreadful UnicodeEncodeError
:
>>> avec ouvrir('file.txt', mode='w') comme file_object:
... unicode_text = vous'xfcber naxefve cafxe9'
... impression >> file_object, unicode_text
...
Traceback (most recent call last):
Fichier "" , line 3, dans
UnicodeEncodeError: 'ascii' codec can't encode character u'xfc'...
Notice how non-Latin characters must be escaped in both Unicode and string literals to avoid a syntax error. Jetez un oeil à cet exemple:
unicode_literal = vous'xfcber naxefve cafxe9'
string_literal = 'xc3xbcber naxc3xafve cafxc3xa9'
Alternatively, you could specify source code encoding according to PEP 263 at the top of the file, but that wasn’t the best practice due to portability issues:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
unescaped_unicode_literal = vous'über naïve café'
unescaped_string_literal = 'über naïve café'
Your best bet is to encode the Unicode string just before printing it. You can do this manually:
avec ouvrir('file.txt', mode='w') comme file_object:
unicode_text = vous'xfcber naxefve cafxe9'
encoded_text = unicode_text.encoder('utf-8')
impression >> file_object, encoded_text
However, a more convenient option is to use the built-in codecs
module:
importation codecs
avec codecs.ouvrir('file.txt', 'w', codage='utf-8') comme file_object:
unicode_text = vous'xfcber naxefve cafxe9'
impression >> file_object, unicode_text
It’ll take care of making appropriate conversions when you need to read or write files.
Buffering Print Calls
In the previous subsection, you learned that print()
delegates printing to a file-like object such as sys.stdout
. Some streams, however, buffer certain I/O operations to enhance performance, which can get in the way. Let’s take a look at an example.
Imagine you were writing a countdown timer, which should append the remaining time to the same line every second:
Your first attempt may look something like this:
importation temps
num_seconds = 3
pour compte à rebours dans renversé(intervalle(num_seconds + 1)):
si compte à rebours > 0:
impression(compte à rebours, fin='...')
temps.sommeil(1)
autre:
impression('Go!')
As long as the compte à rebours
variable is greater than zero, the code keeps appending text without a trailing newline and then goes to sleep for one second. Finally, when the countdown is finished, it prints Go!
and terminates the line.
Unexpectedly, instead of counting down every second, the program idles wastefully for three seconds, and then suddenly prints the entire line at once:
That’s because the operating system buffers subsequent writes to the standard output in this case. You need to know that there are three kinds of streams with respect to buffering:
- Unbuffered
- Line-buffered
- Block-buffered
Unbuffered is self-explanatory, that is, no buffering is taking place, and all writes have immediate effect. UNE line-buffered stream waits before firing any I/O calls until a line break appears somewhere in the buffer, whereas a block-buffered one simply allows the buffer to fill up to a certain size regardless of its content. Standard output is both line-buffered et block-buffered, depending on which event comes first.
Buffering helps to reduce the number of expensive I/O calls. Think about sending messages over a high-latency network, for example. When you connect to a remote server to execute commands over the SSH protocol, each of your keystrokes may actually produce an individual data packet, which is orders of magnitude bigger than its payload. What an overhead! It would make sense to wait until at least a few characters are typed and then send them together. That’s where buffering steps in.
On the other hand, buffering can sometimes have undesired effects as you just saw with the countdown example. To fix it, you can simply tell print()
to forcefully flush the stream without waiting for a newline character in the buffer using its affleurer
flag:
impression(compte à rebours, fin='...', affleurer=Vrai)
C'est tout. Your countdown should work as expected now, but don’t take my word for it. Go ahead and test it to see the difference.
Toutes nos félicitations! At this point, you’ve seen examples of calling print()
that cover all of its parameters. You know their purpose and when to use them. Understanding the signature is only the beginning, however. In the upcoming sections, you’ll see why.
There isn’t an easy way to flush the stream in Python 2, because the impression
statement doesn’t allow for it by itself. You need to get a handle of its lower-level layer, which is the standard output, and call it directly:
importation temps
importation sys
num_seconds = 3
pour compte à rebours dans renversé(intervalle(num_seconds + 1)):
si compte à rebours > 0:
sys.stdout.écrire('%s...' % compte à rebours)
sys.stdout.affleurer()
temps.sommeil(1)
autre:
impression 'Go!'
Alternatively, you could disable buffering of the standard streams either by providing the -u
flag to the Python interpreter or by setting up the PYTHONUNBUFFERED
environment variable:
$ python2 -u countdown.py
$ PYTHONUNBUFFERED=1 python2 countdown.py
Notez que print()
was backported to Python 2 and made available through the __future__
module. Unfortunately, it doesn’t come with the affleurer
parameter:
>>> de __future__ importation print_function
>>> Aidez-moi(impression)
Help on built-in function print in module __builtin__:
print(...)
print(value, ..., sep=' ', end='n', file=sys.stdout)
What you’re seeing here is a docstring du print()
une fonction. You can display docstrings of various objects in Python using the built-in help()
une fonction.
Printing Custom Data Types
Up until now, you only dealt with built-in data types such as strings and numbers, but you’ll often want to print your own abstract data types. Let’s have a look at different ways of defining them.
For simple objects without any logic, whose purpose is to carry data, you’ll typically take advantage of namedtuple
, which is available in the standard library. Named tuples have a neat textual representation out of the box:
>>> de collections importation namedtuple
>>> La personne = namedtuple('Person', 'name age')
>>> jdoe = La personne('John Doe', 42)
>>> impression(jdoe)
Person(name='John Doe', age=42)
That’s great as long as holding data is enough, but in order to add behaviors to the La personne
type, you’ll eventually need to define a class. Jetez un oeil à cet exemple:
classe La personne:
def __init__(soi, prénom, âge):
soi.prénom, soi.âge = prénom, âge
If you now create an instance of the La personne
class and try to print it, you’ll get this bizarre output, which is quite different from the equivalent namedtuple
:
>>> jdoe = La personne('John Doe', 42)
>>> impression(jdoe)
<__main__.Person object at 0x7fcac3fed1d0>
It’s the default representation of objects, which comprises their address in memory, the corresponding class name and a module in which they were defined. You’ll fix that in a bit, but just for the record, as a quick workaround you could combine namedtuple
and a custom class through inheritance:
de collections importation namedtuple
classe La personne(namedtuple('Person', 'name age')):
passer
Your La personne
class has just become a specialized kind of namedtuple
with two attributes, which you can customize.
Remarque: In Python 3, the passer
statement can be replaced with the ellipsis (...
) literal to indicate a placeholder:
This prevents the interpreter from raising IndentationError
due to missing indented block of code.
That’s better than a plain namedtuple
, because not only do you get printing right for free, but you can also add custom methods and properties to the class. However, it solves one problem while introducing another. Remember that tuples, including named tuples, are immutable in Python, so they can’t change their values once created.
It’s true that designing immutable data types is desirable, but in many cases, you’ll want them to allow for change, so you’re back with regular classes again.
Remarque: Following other languages and frameworks, Python 3.7 introduced data classes, which you can think of as mutable tuples. This way, you get the best of both worlds:
>>> de dataclasses importation dataclass
>>> @dataclass
... classe La personne:
... prénom: str
... âge: int
...
... def celebrate_birthday(soi):
... soi.âge += 1
...
>>> jdoe = La personne('John Doe', 42)
>>> jdoe.celebrate_birthday()
>>> impression(jdoe)
Person(name='John Doe', age=43)
The syntax for variable annotations, which is required to specify class fields with their corresponding types, was defined in Python 3.6.
From earlier subsections, you already know that print()
implicitly calls the built-in str()
function to convert its positional arguments into strings. Indeed, calling str()
manually against an instance of the regular La personne
class yields the same result as printing it:
>>> jdoe = La personne('John Doe', 42)
>>> str(jdoe)
'<__main__.Person object at 0x7fcac3fed1d0>'
str()
, in turn, looks for one of two magic methods within the class body, which you typically implement. If it doesn’t find one, then it falls back to the ugly default representation. Those magic methods are, in order of search:
def __str__(self)
def __repr__(self)
The first one is recommended to return a short, human-readable text, which includes information from the most relevant attributes. After all, you don’t want to expose sensitive data, such as user passwords, when printing objects.
However, the other one should provide complete information about an object, to allow for restoring its state from a string. Ideally, it should return valid Python code, so that you can pass it directly to eval()
:
>>> repr(jdoe)
"Person(name='John Doe', age=42)"
>>> type(eval(repr(jdoe)))
Notice the use of another built-in function, repr()
, which always tries to call .__repr__()
in an object, but falls back to the default representation if it doesn’t find that method.
Remarque: Even though print()
itself uses str()
for type casting, some compound data types delegate that call to repr()
on their members. This happens to lists and tuples, for example.
Consider this class with both magic methods, which return alternative string representations of the same object:
classe Utilisateur:
def __init__(soi, s'identifier, mot de passe):
soi.s'identifier = s'identifier
soi.mot de passe = mot de passe
def __str__(soi):
revenir soi.s'identifier
def __repr__(soi):
revenir F"User('self.login', 'self.password')"
If you print a single object of the Utilisateur
class, then you won’t see the password, because print(user)
appellera str(user)
, which eventually will invoke user.__str__()
:
>>> utilisateur = Utilisateur('jdoe', 's3cret')
>>> impression(utilisateur)
jdoe
However, if you put the same utilisateur
variable inside a list by wrapping it in square brackets, then the password will become clearly visible:
>>> impression([[[[utilisateur])
[User('jdoe', 's3cret')]
That’s because sequences, such as lists and tuples, implement their .__str__()
method so that all of their elements are first converted with repr()
.
Python gives you a lot of freedom when it comes to defining your own data types if none of the built-in ones meet your needs. Some of them, such as named tuples and data classes, offer string representations that look good without requiring any work on your part. Still, for the most flexibility, you’ll have to define a class and override its magic methods described above.
The semantics of .__str__()
et .__repr__()
didn’t change since Python 2, but you must remember that strings were nothing more than glorified byte arrays back then. To convert your objects into proper Unicode, which was a separate data type, you’d have to provide yet another magic method: .__unicode__()
.
Here’s an example of the same Utilisateur
class in Python 2:
classe Utilisateur(objet):
def __init__(soi, s'identifier, mot de passe):
soi.s'identifier = s'identifier
soi.mot de passe = mot de passe
def __unicode__(soi):
revenir soi.s'identifier
def __str__(soi):
revenir unicode(soi).encoder('utf-8')
def __repr__(soi):
utilisateur = vous"User('%s', '%s')" % (soi.s'identifier, soi.mot de passe)
revenir utilisateur.encoder('unicode_escape')
As you can see, this implementation delegates some work to avoid duplication by calling the built-in unicode()
function on itself.
Tous les deux .__str__()
et .__repr__()
methods must return strings, so they encode Unicode characters into specific byte representations called jeux de caractères. UTF-8 is the most widespread and safest encoding, while unicode_escape
is a special constant to express funky characters, such as é
, as escape sequences in plain ASCII, such as xe9
.
le impression
statement is looking for the magic .__str__()
method in the class, so the chosen charset must correspond to the one used by the terminal. For example, default encoding in DOS and Windows is CP 852 rather than UTF-8, so running this can result in a UnicodeEncodeError
or even garbled output:
>>> utilisateur = Utilisateur(vous'u043du0438u043au0438u0442u0430', vous's3cret')
>>> impression utilisateur
đŻđŞđ║đŞĐéđ░
However, if you ran the same code on a system with UTF-8 encoding, then you’d get the proper spelling of a popular Russian name:
>>> utilisateur = Utilisateur(vous'u043du0438u043au0438u0442u0430', vous's3cret')
>>> impression utilisateur
никита
It’s recommended to convert strings to Unicode as early as possible, for example, when you’re reading data from a file, and use it consistently everywhere in your code. At the same time, you should encode Unicode back to the chosen character set right before presenting it to the user.
It seems as if you have more control over string representation of objects in Python 2 because there’s no magic .__unicode__()
method in Python 3 anymore. You may be asking yourself if it’s possible to convert an object to its byte string representation rather than a Unicode string in Python 3. It’s possible, with a special .__bytes__()
method that does just that:
>>> classe Utilisateur(objet):
... def __init__(soi, s'identifier, mot de passe):
... soi.s'identifier = s'identifier
... soi.mot de passe = mot de passe
...
... def __bytes__(soi): # Python 3
... revenir soi.s'identifier.encoder('utf-8')
...
>>> utilisateur = Utilisateur(vous'u043du0438u043au0438u0442u0430', vous's3cret')
>>> octets(utilisateur)
b'xd0xbdxd0xb8xd0xbaxd0xb8xd1x82xd0xb0'
Using the built-in bytes()
function on an instance delegates the call to its __bytes__()
method defined in the corresponding class.
Understanding Python Print
You know Comment utiliser print()
quite well at this point, but knowing quoi it is will allow you to use it even more effectively and consciously. After reading this section, you’ll understand how printing in Python has improved over the years.
Print Is a Function in Python 3
You’ve seen that print()
is a function in Python 3. More specifically, it’s a built-in function, which means that you don’t need to import it from anywhere:
>>> impression
It’s always available in the global namespace so that you can call it directly, but you can also access it through a module from the standard library:
>>> importation builtins
>>> builtins.impression
This way, you can avoid name collisions with custom functions. Let’s say you wanted to redéfinir print()
so that it doesn’t append a trailing newline. At the same time, you wanted to rename the original function to something like println()
:
>>> importation builtins
>>> println = builtins.impression
>>> def impression(*args, **kwargs):
... builtins.impression(*args, **kwargs, fin='')
...
>>> println('hello')
Bonjour
>>> impression('hello n')
Bonjour
Now you have two separate printing functions just like in the Java programming language. You’ll define custom print()
functions in the mocking section later as well. Also, note that you wouldn’t be able to overwrite print()
in the first place if it wasn’t a function.
D'autre part, print()
isn’t a function in the mathematical sense, because it doesn’t return any meaningful value other than the implicit Aucun
:
>>> valeur = impression('hello world')
Bonjour le monde
>>> impression(valeur)
Aucun
Such functions are, in fact, procedures or subroutines that you call to achieve some kind of side-effect, which ultimately is a change of a global state. Dans le cas de print()
, that side-effect is showing a message on the standard output or writing to a file.
Because print()
is a function, it has a well-defined signature with known attributes. You can quickly find its documentation using the editor of your choice, without having to remember some weird syntax for performing a certain task.
Besides, functions are easier to étendre. Adding a new feature to a function is as easy as adding another keyword argument, whereas changing the language to support that new feature is much more cumbersome. Think of stream redirection or buffer flushing, for example.
Another benefit of print()
being a function is composabilité. Functions are so-called first-class objects or first-class citizens in Python, which is a fancy way of saying they’re values just like strings or numbers. This way, you can assign a function to a variable, pass it to another function, or even return one from another. print()
isn’t different in this regard. For instance, you can take advantage of it for dependency injection:
def Télécharger(url, bûche=impression):
bûche(F'Downloading url')
# ...
def custom_print(*args):
passer # Do not print anything
Télécharger('/js/app.js', bûche=custom_print)
Here, the bûche
parameter lets you inject a callback function, which defaults to print()
but can be any callable. In this example, printing is completely disabled by substituting print()
with a dummy function that does nothing.
Remarque: UNE dépendance is any piece of code required by another bit of code.
Dependency injection is a technique used in code design to make it more testable, reusable, and open for extension. You can achieve it by referring to dependencies indirectly through abstract interfaces and by providing them in a pousser plutôt que tirez mode.
There’s a funny explanation of dependency injection circulating on the Internet:
Dependency injection for five-year-olds
When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn’t want you to have. You might even be looking for something we don’t even have or which has expired.
What you should be doing is stating a need, “I need something to drink with lunch,” and then we will make sure you have something when you sit down to eat.
– John Munsch, 28 October 2009. (La source)
Composition allows you to combine a few functions into a new one of the same kind. Let’s see this in action by specifying a custom error()
function that prints to the standard error stream and prefixes all messages with a given log level:
>>> de functools importation partiel
>>> importation sys
>>> réorienter = lambda une fonction, courant: partiel(une fonction, fichier=courant)
>>> préfixe = lambda une fonction, préfixe: partiel(une fonction, préfixe)
>>> Erreur = préfixe(réorienter(impression, sys.stderr), '[ERROR]')
>>> Erreur('Something went wrong')
[ERROR] Something went wrong
This custom function uses partial functions to achieve the desired effect. It’s an advanced concept borrowed from the functional programming paradigm, so you don’t need to go too deep into that topic for now. However, if you’re interested in this topic, I recommend taking a look at the functools
module.
Unlike statements, functions are values. That means you can mix them with expressions, in particular, lambda expressions. Instead of defining a full-blown function to replace print()
with, you can make an anonymous lambda expression that calls it:
>>> Télécharger('/js/app.js', lambda msg: impression('[INFO]', msg))
[INFO] Downloading /js/app.js
However, because a lambda expression is defined in place, there’s no way of referring to it elsewhere in the code.
Remarque: In Python, you can’t put statements, such as assignments, conditional statements, loops, and so on, in an anonymous lambda function. It has to be a single expression!
Another kind of expression is a ternary conditional expression:
>>> utilisateur = 'jdoe'
>>> impression('Hi!') si utilisateur est Aucun autre impression(F'Hi, user.')
Hi, jdoe.
Python has both conditional statements and conditional expressions. The latter is evaluated to a single value that can be assigned to a variable or passed to a function. In the example above, you’re interested in the side-effect rather than the value, which evaluates to Aucun
, so you simply ignore it.
As you can see, functions allow for an elegant and extensible solution, which is consistent with the rest of the language. In the next subsection, you’ll discover how not having print()
as a function caused a lot of headaches.
Print Was a Statement in Python 2
UNE déclaration is an instruction that may evoke a side-effect when executed but never evaluates to a value. In other words, you wouldn’t be able to print a statement or assign it to a variable like this:
résultat = impression 'hello world'
That’s a syntax error in Python 2.
Here are a few more examples of statements in Python:
- assignment:
=
- conditional:
si
- loop:
tandis que
- affirmation:
affirmer
Remarque: Python 3.8 brings a controversial walrus operator (:=
), which is an assignment expression. With it, you can evaluate an expression and assign the result to a variable at the same time, even within another expression!
Take a look at this example, which calls an expensive function once and then reuses the result for further computation:
# Python 3.8+
valeurs = [[[[y := F(X), y**2, y**3]
This is useful for simplifying the code without losing its efficiency. Typically, performant code tends to be more verbose:
y = F(X)
valeurs = [[[[y, y**2, y**3]
The controversy behind this new piece of syntax caused a lot of argument. An abundance of negative comments and heated debates eventually led Guido van Rossum to step down from the Benevolent Dictator For Life or BDFL position.
Statements are usually comprised of reserved keywords such as si
, pour
, ou impression
that have fixed meaning in the language. You can’t use them to name your variables or other symbols. That’s why redefining or mocking the impression
statement isn’t possible in Python 2. You’re stuck with what you get.
Furthermore, you can’t print from anonymous functions, because statements aren’t accepted in lambda expressions:
>>> lambda: impression 'hello world'
Fichier "" , line 1
lambda: impression 'hello world'
^
SyntaxError: Syntaxe invalide
The syntax of the impression
statement is ambiguous. Sometimes you can add parentheses around the message, and they’re completely optional:
>>> impression 'Please wait...'
S'il vous plaît, attendez...
>>> impression('Please wait...')
S'il vous plaît, attendez...
At other times they change how the message is printed:
>>> impression 'My name is', 'John'
My name is John
>>> impression('My name is', 'John')
('My name is', 'John')
String concatenation can raise a TypeError
due to incompatible types, which you have to handle manually, for example:
>>> valeurs = [[[['jdoe', 'is', 42, 'years old']
>>> impression ' '.joindre(carte(str, valeurs))
jdoe is 42 years old
Compare this with similar code in Python 3, which leverages sequence unpacking:
>>> valeurs = [[[['jdoe', 'is', 42, 'years old']
>>> impression(*valeurs) # Python 3
jdoe is 42 years old
There aren’t any keyword arguments for common tasks such as flushing the buffer or stream redirection. You need to remember the quirky syntax instead. Even the built-in help()
function isn’t that helpful with regards to the impression
statement:
>>> Aidez-moi(impression)
Fichier "" , line 1
Aidez-moi(impression)
^
SyntaxError: Syntaxe invalide
Trailing newline removal doesn’t work quite right, because it adds an unwanted space. You can’t compose multiple impression
statements together, and, on top of that, you have to be extra diligent about character encoding.
The list of problems goes on and on. If you’re curious, you can jump back to the previous section and look for more detailed explanations of the syntax in Python 2.
However, you can mitigate some of those problems with a much simpler approach. It turns out the print()
function was backported to ease the migration to Python 3. You can import it from a special __future__
module, which exposes a selection of language features released in later Python versions.
Remarque: You may import future functions as well as baked-in language constructs such as the avec
statement.
To find out exactly what features are available to you, inspect the module:
>>> importation __future__
>>> __future__.all_feature_names
['nested_scopes'['nested_scopes'['nested_scopes'['nested_scopes'
'generators',
'division',
'absolute_import',
'with_statement',
'print_function',
'unicode_literals']
You could also call dir(__future__)
, but that would show a lot of uninteresting internal details of the module.
To enable the print()
function in Python 2, you need to add this import statement at the beginning of your source code:
de __future__ importation print_function
From now on the impression
statement is no longer available, but you have the print()
function at your disposal. Note that it isn’t the same function like the one in Python 3, because it’s missing the affleurer
keyword argument, but the rest of the arguments are the same.
Other than that, it doesn’t spare you from managing character encodings properly.
Here’s an example of calling the print()
function in Python 2:
>>> de __future__ importation print_function
>>> importation sys
>>> impression('I am a function in Python', sys.version_info.Majeur)
I am a function in Python 2
You now have an idea of how printing in Python evolved and, most importantly, understand why these backward-incompatible changes were necessary. Knowing this will surely help you become a better Python programmer.
Printing With Style
If you thought that printing was only about lighting pixels up on the screen, then technically you’d be right. However, there are ways to make it look cool. In this section, you’ll find out how to format complex data structures, add colors and other decorations, build interfaces, use animation, and even play sounds with text!
Pretty-Printing Nested Data Structures
Computer languages allow you to represent data as well as executable code in a structured way. Unlike Python, however, most languages give you a lot of freedom in using whitespace and formatting. This can be useful, for example in compression, but it sometimes leads to less readable code.
Pretty-printing is about making a piece of data or code look more appealing to the human eye so that it can be understood more easily. This is done by indenting certain lines, inserting newlines, reordering elements, and so forth.
Python comes with the pprint
module in its standard library, which will help you in pretty-printing large data structures that don’t fit on a single line. Because it prints in a more human-friendly way, many popular REPL tools, including JupyterLab and IPython, use it by default in place of the regular print()
une fonction.
Remarque: To toggle pretty printing in IPython, issue the following command:
Dans [1]: %pprint
Pretty printing has been turned OFF
Dans [2]: %pprint
Pretty printing has been turned ON
This is an example of Magic in IPython. There are a lot of built-in commands that start with a percent sign (%
), but you can find more on PyPI, or even create your own.
If you don’t care about not having access to the original print()
function, then you can replace it with pprint()
in your code using import renaming:
>>> de pprint importation pprint comme impression
>>> impression
Personally, I like to have both functions at my fingertips, so I’d rather use something like pp
as a short alias:
de pprint importation pprint comme pp
At first glance, there’s hardly any difference between the two functions, and in some cases there’s virtually none:
>>> impression(42)
42
>>> pp(42)
42
>>> impression('hello')
Bonjour
>>> pp('hello')
'hello' # Did you spot the difference?
That’s because pprint()
appels repr()
instead of the usual str()
for type casting, so that you may evaluate its output as Python code if you want to. The differences become apparent as you start feeding it more complex data structures:
>>> Les données = 'powers': [[[[X**dix pour X dans intervalle(dix)]
>>> pp(Les données)
'powers':[0[0[0[0
1,
1024,
59049,
1048576,
9765625,
60466176,
282475249,
1073741824,
3486784401]
The function applies reasonable formatting to improve readability, but you can customize it even further with a couple of parameters. For example, you may limit a deeply nested hierarchy by showing an ellipsis below a given level:
>>> villes = 'USA': 'Texas': 'Dallas': [[[['Irving']
>>> pp(villes, profondeur=3)
'USA': 'Texas': 'Dallas': [...]
The ordinary print()
also uses ellipses but for displaying recursive data structures, which form a cycle, to avoid stack overflow error:
>>> articles = [[[[1, 2, 3]
>>> articles.ajouter(articles)
>>> impression(articles)
[123[123[123[123[...]]
However, pprint()
is more explicit about it by including the unique identity of a self-referencing object:
>>> pp(articles)
[123[123[123[123]
>>> identifiant(articles)
140635757287688
The last element in the list is the same object as the entire list.
Remarque: Recursive or very large data sets can be dealt with using the reprlib
module as well:
>>> importation reprlib
>>> reprlib.repr([[[[X**dix pour X dans intervalle(dix)])
'[0, 1, 1024, 59049, 1048576, 9765625, ...]'
This module supports most of the built-in types and is used by the Python debugger.
pprint()
automatically sorts dictionary keys for you before printing, which allows for consistent comparison. When you’re comparing strings, you often don’t care about a particular order of serialized attributes. Anyways, it’s always best to compare actual dictionaries before serialization.
Dictionaries often represent JSON data, which is widely used on the Internet. To correctly serialize a dictionary into a valid JSON-formatted string, you can take advantage of the JSON
module. It too has pretty-printing capabilities:
>>> importation JSON
>>> Les données = 'username': 'jdoe', 'password': 's3cret'
>>> laid = JSON.décharges(Les données)
>>> jolie = JSON.décharges(Les données, retrait=4, sort_keys=Vrai)
>>> impression(laid)
"username": "jdoe", "password": "s3cret"
>>> impression(jolie)
"password": "s3cret",
"username": "jdoe"
Notice, however, that you need to handle printing yourself, because it’s not something you’d typically want to do. Similarly, the pprint
module has an additional pformat()
function that returns a string, in case you had to do something other than printing it.
Surprisingly, the signature of pprint()
is nothing like the print()
function’s one. You can’t even pass more than one positional argument, which shows how much it focuses on printing data structures.
Adding Colors With ANSI Escape Sequences
As personal computers got more sophisticated, they had better graphics and could display more colors. However, different vendors had their own idea about the API design for controlling it. That changed a few decades ago when people at the American National Standards Institute decided to unify it by defining ANSI escape codes.
Most of today’s terminal emulators support this standard to some degree. Until recently, the Windows operating system was a notable exception. Therefore, if you want the best portability, use the colorama
library in Python. It translates ANSI codes to their appropriate counterparts in Windows while keeping them intact in other operating systems.
To check if your terminal understands a subset of the ANSI escape sequences, for example, related to colors, you can try using the following command:
My default terminal on Linux says it can display 256 distinct colors, while xterm gives me only 8. The command would return a negative number if colors were unsupported.
ANSI escape sequences are like a markup language for the terminal. In HTML you work with tags, such as ou
, to change how elements look in the document. These tags are mixed with your content, but they’re not visible themselves. Similarly, escape codes won’t show up in the terminal as long as it recognizes them. Otherwise, they’ll appear in the literal form as if you were viewing the source of a website.
As its name implies, a sequence must begin with the non-printable Esc character, whose ASCII value is 27, sometimes denoted as 0x1b
in hexadecimal or 033
in octal. You may use Python number literals to quickly verify it’s indeed the same number:
>>> 27 == 0x1b == 0o33
Vrai
Additionally, you can obtain it with the e
escape sequence in the shell:
The most common ANSI escape sequences take the following form:
Élément | La description | Example |
---|---|---|
Esc | non-printable escape character |
|