Votre guide de la fonction Python print () – Real Python – Bien choisir son serveur d impression
[bzkshopping keyword= »Minecraft » count= »8″ template= »grid »]
Si vous êtes comme la plupart des utilisateurs de Python, moi y compris, vous avez probablement commencé votre aventure Python en vous renseignant sur impression()
. Cela vous a aidé à écrire le vôtre Bonjour le monde
bon mot. Vous pouvez l'utiliser pour afficher des messages formatés à l'écran et peut-être trouver des bogues. Mais si vous pensez que c'est tout ce qu'il y a à savoir sur Python impression()
fonction, alors vous manquez beaucoup de choses!
Continuez à lire pour profiter pleinement de cette petite fonction apparemment ennuyeuse et méconnue. Ce tutoriel vous permettra de vous familiariser avec l'utilisation de Python impression()
effectivement. Cependant, préparez-vous à une plongée approfondie en parcourant les sections. Vous serez peut-être surpris de voir à quel point impression()
a à offrir!
Si vous êtes un débutant complet, vous bénéficierez le plus de la lecture de la première partie de ce didacticiel, qui illustre les principes de base de l'impression en Python. Sinon, n'hésitez pas à sauter cette partie et à sauter comme bon vous semble.
Sommaire
L'impression en bref
Commençons par examiner quelques exemples concrets d’impression en Python. À la fin de cette section, vous connaîtrez tous les modes d'appels possibles impression()
. Ou, dans le jargon du programmeur, vous diriez que vous serez familier avec le signature de fonction.
Appel impression()
L'exemple le plus simple d'utilisation de Python impression()
ne nécessite que quelques touches:
Vous ne passez aucun argument, mais vous devez tout de même mettre des parenthèses vides à la fin, ce qui indique à Python d'exécuter réellement la fonction plutôt que de simplement y faire référence par son nom.
Cela produira un caractère de nouvelle ligne invisible, qui à son tour provoquera l'apparition d'une ligne vide sur votre écran. Tu peux appeler impression()
plusieurs fois comme ceci pour ajouter un 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 ces caractères non imprimables avec de petits graphiques.
Le mot «caractère» est quelque peu inapproprié dans ce cas, car une nouvelle ligne comporte souvent plus d'un caractère. Par exemple, le système d'exploitation Windows, ainsi que le protocole HTTP, représentent les retours à la ligne avec une paire de caractères. Parfois, vous devez tenir compte de ces différences pour concevoir des programmes vraiment portables.
Pour découvrir ce qui constitue une nouvelle ligne dans votre système d’exploitation, utilisez la fonction intégrée de Python os
module.
Cela vous dira immédiatement que les fenêtres et DOS représentent la nouvelle ligne comme une séquence de r
suivie par n
:
>>> importer os
>>> os.pas de ligne
' r n'
Sur Unix, Linux, et les versions récentes de macOS, c’est un single n
personnage:
>>> importer os
>>> os.pas de ligne
' n'
Le classique Mac OS X, cependant, s'en tient à sa propre philosophie de «penser différemment» en choisissant encore une autre représentation:
>>> importer os
>>> os.pas de ligne
' 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 () pour désigner 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 les caractères spéciaux tels que ceux-ci:
\
: barre oblique inverseb
: retour arrièret
: languetter
: retour chariot (CR)n
: nouvelle ligne, également appelée saut de ligne (LF)
Les deux derniers 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 courante, tandis que la seconde ferait avancer le rouleau jusqu'à la ligne suivante.
En comparant les Codes de caractères ASCII, vous verrez que placer une barre oblique inverse devant un caractère change complètement sa signification. Cependant, tous les caractères ne le permettent pas, seuls les caractères spéciaux.
Pour comparer les codes de caractères ASCII, vous pouvez utiliser la fonction intégrée ord ()
fonction:
>>> ord(«r»)
114
>>> ord(' r')
13
Gardez à l'esprit que, pour former une séquence d'échappement correcte, il ne doit y avoir aucun espace entre la barre oblique inverse et une lettre!
Comme tu viens de le voir, appeler impression()
sans argument entraîne un ligne blanche, qui est une ligne composée uniquement du caractère de nouvelle ligne. Ne confondez pas cela avec un ligne vide, qui ne contient aucun caractère, pas même la nouvelle ligne!
Vous pouvez utiliser les chaînes littérales de Python pour visualiser ces deux éléments:
' n' # Ligne blanche
'' # Ligne vide
Le premier a un caractère, tandis que le second n'a pas de contenu.
Noter: 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()
"Une ligne de texte."
Cela supprime tout espace blanc à la fin 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 existe plusieurs moyens d'y parvenir.
Tout d'abord, vous pouvez passer une chaîne littérale 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 peut être placé entre guillemets simples ('
) ou des guillemets doubles ("
). Selon le guide de style officiel PEP 8, vous devez simplement en choisir un et continuer à l'utiliser de manière cohérente. Il n'y a pas de différence, sauf si vous devez en imbriquer un dans un autre.
Par exemple, vous ne pouvez pas utiliser de guillemets doubles pour le littéral et inclure également des guillemets doubles à l'intérieur de celui-ci, car cela est ambigu pour l'interpréteur Python:
"Mon livre favori est "Python Des trucs"" # Mal!
Ce que vous voulez faire est de mettre le texte, qui contient des guillemets doubles, entre guillemets simples:
"Mon livre préféré est" Python Tricks ""
La même astuce fonctionnerait dans l'autre sens:
"Mon livre préféré est" Python Tricks ""
Vous pouvez également utiliser les séquences de caractères d'échappement mentionnées précédemment, pour que Python traite ces guillemets internes littéralement comme faisant partie de la chaîne littérale:
"Mon livre favori est "Astuces Python ""
S'échapper est bien et dandy, mais cela peut parfois gêner. Plus précisément, lorsque vous avez besoin que votre chaîne contienne relativement de nombreux caractères de barre oblique inverse sous forme littérale.
Un exemple classique est un chemin de fichier sous Windows:
'C: Utilisateurs jdoe' # Mal!
«C:\Utilisateurs\jdoe '
Remarquez comment chaque caractère de barre oblique inverse doit être échappé avec une autre barre oblique inverse.
Ceci est encore plus important avec les expressions régulières, qui se compliquent rapidement en raison de l'utilisation intensive de caractères spéciaux:
'^\w:\\(? :(? :( ?:[^[^[^[^\\]+)? | (?:[^[^[^[^\\]+)\\[^[^[^[^\\]+) *) $ '
Heureusement, vous pouvez désactiver complètement l'échappement des caractères à l'aide de littéraux de chaîne brute. Ajoutez simplement 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, non?
Il existe quelques préfixes supplémentaires qui donnent une signification particulière aux littéraux de chaîne en Python, mais vous ne les aborderez pas ici.
Enfin, vous pouvez définir des littéraux de chaîne multilignes en les plaçant entre '' '
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, placez simplement 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 de la fonction intégrée habillage de texte
module:
>>> importer 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évoué(paragraphe).déshabiller())
Ceci est un exemple
d'une chaîne multiligne
en Python.
Cela prendra en charge la suppression de l'indentation des paragraphes pour vous. Il existe également quelques autres fonctions utiles dans habillage de texte
pour l'alignement de texte que vous trouverez dans un traitement de texte.
Deuxièmement, vous pouvez extraire ce message dans sa propre variable avec un nom significatif pour améliorer la lisibilité et promouvoir la réutilisation du code:
>>> un message = 'Veuillez patienter pendant le chargement du programme ...'
>>> impression(un message)
Enfin, vous pouvez passer une expression, comme la concaténation de chaînes, à évaluer avant d'imprimer le résultat:
>>> importer os
>>> impression('Bonjour, ' + os.getlogin() + '! Comment allez-vous?')
Bonjour jdoe! Comment vas-tu?
En fait, il existe une douzaine de façons de formater des messages en Python. Je vous encourage vivement à jeter un coup d'œil aux f-strings, introduites dans Python 3.6, car elles offrent la syntaxe la plus concise de toutes:
>>> importer os
>>> impression(F'Bonjour, os.getlogin()! Comment allez-vous?')
De plus, les chaînes f vous éviteront de faire une erreur courante, qui est d'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 cela:
>>> 'Mon âge est ' + 42
Traceback (dernier appel le plus récent):
Déposer "", ligne 1, dans
'Mon âge est ' + 42
Erreur-type: ne peut concaténer que str (pas "int") en 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 joindre ensemble:
>>> 'Mon âge est ' + str(42)
'Mon âge est de 42 ans'
À moins que vous ne gériez vous-même de telles erreurs, l'interpréteur Python vous informera d'un problème en affichant une trace.
Noter: 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 numéro:
Les types de données intégrés ont une représentation sous forme de chaîne prédéfinie prête à l'emploi, 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 transmettiez un littéral, une variable ou une expression. Contrairement à de nombreuses autres fonctions, cependant, impression()
acceptera n'importe quoi quel que soit son type.
Jusqu'à présent, vous n'avez regardé que 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 ressort:
>>> 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('Nom': «Alice», 'âge': 42) #
'nom': 'Alice', 'âge': 42
>>> impression('Bonjour') #
Bonjour
Attention aux Aucun
constante, cependant. Bien qu'il soit utilisé pour indiquer une absence de valeur, il apparaîtra comme 'Aucun'
plutôt qu'une chaîne vide:
Comment ça marche impression()
savoir comment travailler avec tous ces différents types? Eh bien, la réponse courte est que non. Il appelle implicitement str ()
dans les coulisses pour taper cast n'importe quel objet dans une chaîne. Ensuite, il traite les chaînes de manière uniforme.
Plus loin dans ce didacticiel, vous apprendrez à utiliser ce mécanisme pour imprimer des types de données personnalisés tels que vos classes.
D'accord, vous pouvez maintenant appeler impression()
avec un seul argument ou sans aucun argument. Vous savez comment imprimer des messages fixes ou formatés sur l'écran. La prochaine sous-section développera un peu la mise en forme des messages.
Pour obtenir le même résultat dans la génération de langue précédente, vous souhaitez normalement supprimer les parenthèses entourant le texte:
# Python 2
impression
impression 'S'il vous plaît, attendez...'
impression 'Bonjour, % s! Comment allez-vous?' % os.getlogin()
impression 'Bonjour, % s. Votre âge est %ré». % (Nom, âge)
C'est parce que impression
n’était pas une fonction à l’époque, comme vous le verrez dans la section suivante. Notez cependant que dans certains cas, les parenthèses en Python sont redondantes. Cela ne ferait pas de mal de les inclure car ils seraient simplement ignorés. Cela signifie-t-il que vous devriez utiliser le impression
déclaration comme s'il s'agissait d'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 ronds font en fait 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 du tout inclus les crochets.
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 obtiendrez également un tuple en ajoutant une virgule à la fin du 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...',)
En fin de compte, vous ne devriez pas appeler impression
avec des crochets en Python 2. Bien que, pour être tout à fait précis, vous pouvez contourner ce problème à l'aide d'un __avenir__
import, dont vous en apprendrez plus dans la section correspondante.
Séparer plusieurs arguments
Vous avez vu impression()
appelé sans aucun argument pour produire une ligne vide, puis appelé 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 mise en forme de message, où vous souhaitez joindre quelques éléments ensemble.
Les arguments peuvent être passés à une fonction de plusieurs manières. Une façon consiste à 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
Étant donné que les arguments peuvent être identifiés de manière unique 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 doivent suivre strictement 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 positionnels grâce au * args
paramètre.
Jetons un œil à cet exemple:
>>> importer 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 Jdo et je suis 42 ''
.
Notez qu'il a également pris soin de la conversion de type appropriée en appelant implicitement str ()
sur chaque argument avant de les réunir. 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):
Déposer "", ligne 1, dans
impression('Mon âge est: ' + 42)
Erreur-type: ne peut concaténer que str (pas "int") en str
En plus d'accepter un nombre variable d'arguments positionnels, impression()
définit quatre nommés ou arguments de mots clés, qui sont facultatifs car ils ont tous des valeurs par défaut. Vous pouvez consulter leur brève documentation en appelant aide (impression)
de l'interprète interactif.
Concentrons-nous sur SEP
juste pour l'instant. Ça signifie séparateur et se voit attribuer un seul espace (''
) par défaut. Il détermine la valeur avec laquelle joindre des éléments.
Il doit s'agir d'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 souhaitez 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 sous forme de lignes séparées. Dans ce cas, passez simplement le caractère de nouvelle ligne échappé décrit précédemment:
>>> impression('Bonjour', 'monde', SEP=' n')
Bonjour
monde
Un exemple plus utile de la SEP
paramètre imprimerait quelque chose comme les chemins de fichiers:
>>> impression('domicile', 'utilisateur', 'documents', SEP='/')
accueil / utilisateur / documents
N'oubliez pas que le séparateur se situe entre les éléments, pas autour d'eux, vous devez donc en tenir compte d'une manière ou d'une autre:
>>> impression('/domicile', 'utilisateur', 'documents', SEP='/')
/ home / utilisateur / documents
>>> impression('', 'domicile', 'utilisateur', 'documents', SEP='/')
/ home / utilisateur / documents
Plus précisément, vous pouvez insérer une barre oblique (/
) dans le premier argument de position, ou utilisez une chaîne vide comme premier argument pour appliquer la barre oblique.
Noter: Soyez prudent lorsque vous joignez des éléments d'une liste ou d'un tuple.
Le faire manuellement se traduira par un bien connu Erreur-type
si au moins l'un des éléments n'est pas une chaîne:
>>> impression(''.rejoindre([[[['jdoe est', 42, 'ans']))
Traceback (dernier appel le plus récent):
Déposer "", ligne 1, dans
impression(','.rejoindre([[[['jdoe est', 42, 'ans']))
Erreur-type: élément de séquence 1: instance de str attendue, int trouvé
Il est plus sûr de simplement décompresser la séquence avec l’opérateur étoile (*
) et laissez impression()
moulage de type poignée:
>>> impression(*[[[['jdoe est', 42, 'ans'])
jdoe a 42 ans
Le déballage est en fait la même chose que l'appel 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, 'Astuces Python', «Dan Bader», SEP=',')
1, astuces Python, Dan Bader
Cela ne gérerait pas correctement les cas extrêmes tels que les virgules d'échappement, mais pour des cas d'utilisation simples, cela devrait le faire. La ligne ci-dessus apparaîtra dans la fenêtre de votre terminal. Pour l'enregistrer dans un fichier, vous devez rediriger la sortie. Plus loin dans cette section, vous verrez comment utiliser impression()
pour écrire du texte dans des fichiers directement à partir de Python.
Finalement, le SEP
Le 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='->')
nœud -> enfant -> enfant
Dans les sous-sections à venir, vous découvrirez les arguments de mots clés restants de la impression()
fonction.
Pour imprimer plusieurs éléments dans Python 2, vous devez supprimer les parenthèses autour d'eux, comme avant:
>>> # Python 2
>>> importer os
>>> impression 'Mon nom est', os.getlogin(), 'et je suis', 42
Je m'appelle jdoe et j'ai 42 ans
Si vous les avez conservés, en revanche, vous passerez un seul élément de tuple au impression
déclaration:
>>> # Python 2
>>> importer os
>>> impression('Mon nom est', os.getlogin(), 'et je suis', 42)
('Je m'appelle', 'jdoe', 'et je suis', 42)
De plus, il n'y a aucun moyen de modifier le séparateur par défaut des éléments joints dans Python 2, donc une solution de contournement consiste à utiliser l'interpolation de chaîne comme ceci:
>>> # Python 2
>>> importer os
>>> impression 'Mon nom est % s et je suis %ré' % (os.getlogin(), 42)
Je m'appelle jdoe et j'ai 42 ans
C'était la manière par défaut de formater les chaînes jusqu'à ce que .format()
méthode a été rétroportée à partir de Python 3.
Prévention des sauts de ligne
Parfois, vous ne souhaitez pas terminer votre message par une nouvelle ligne de fin afin que les appels suivants à 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'invitation à saisir l'utilisateur. 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 permettent de décider d'ajouter ou non une nouvelle ligne. Par exemple, en Java et C #, vous avez deux fonctions distinctes, tandis que d'autres langages vous obligent à ajouter explicitement n
à la fin d'une chaîne littérale.
Voici quelques exemples de syntaxe dans ces langages:
Langue | Exemple |
---|---|
Perl | imprimer "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 profiter d'un autre argument de mot-clé, finir
, qui dicte par quoi terminer la ligne.
En termes de sémantique, le finir
paramètre est presque identique au 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
, elle aura le même effet que la valeur par défaut. - Si égal à une chaîne vide (
''
), il supprimera la nouvelle ligne.
Vous comprenez maintenant ce qui se passe sous le capot lorsque vous appelez impression()
sans arguments. Étant donné que vous ne fournissez aucun argument de position à la fonction, il n'y a rien à joindre et le séparateur par défaut n'est donc pas du tout utilisé. Cependant, la valeur par défaut de finir
s'applique toujours, et une ligne vide apparaît.
Noter: Vous vous demandez peut-être pourquoi finir
a une valeur par défaut fixe plutôt que ce qui a du sens sur votre système d'exploitation.
Eh bien, vous n’avez pas à vous soucier de la représentation de nouvelle ligne sur différents systèmes d’exploitation lors de l’impression, car impression()
gérera automatiquement la conversion. N'oubliez pas 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 nligne3 ')
ligne 1
ligne 2
ligne3
Si vous deviez essayer d'imprimer de manière forcée un caractère de nouvelle ligne spécifique à Windows sur une machine Linux, par exemple, vous vous retrouveriez avec une sortie interrompue:
>>> impression('ligne 1 r nligne 2 r nligne3 ')
ligne3
D'un autre côté, lorsque vous ouvrez un fichier à lire avec ouvert()
, vous n’avez pas besoin non plus de vous soucier de la représentation de nouvelle ligne. La fonction traduira toute nouvelle ligne spécifique au système rencontrée en une ' n'
. En même temps, vous avez le contrôle sur la façon dont les nouvelles lignes doivent être traitées à la fois 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 finir
argument de mot-clé:
impression('Vérification de l'intégrité des fichiers ...', finir='')
# (...)
impression('d'accord')
Même si ce sont deux séparés impression()
les appels, qui peuvent s’exécuter très longtemps, vous ne verrez finalement qu’une seule ligne. Tout d'abord, cela ressemblera à ceci:
Vérification de l'intégrité des fichiers ...
Cependant, après le deuxième appel à impression()
, la même ligne apparaîtra à l'écran comme:
Vérification de l'intégrité du fichier ... ok
Comme avec SEP
, vous pouvez utiliser finir
pour joindre des morceaux individuels dans une grosse goutte de texte avec un séparateur personnalisé. Au lieu de joindre plusieurs arguments, cependant, il ajoutera le texte de chaque appel de fonction sur la même ligne:
impression('La première phrase', finir=». ')
impression('La deuxième phrase', finir=». ')
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 mot-clé:
impression('Mercure', 'Vénus', 'La terre', SEP=',', finir=',')
impression('Mars', 'Jupiter', 'Saturne', SEP=',', finir=',')
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 peu de remplissage supplémentaire autour de celui-ci:
impression(«L'impression en bref», finir=' n * ')
impression("Appel de Print", finir=' n * ')
impression(«Séparer plusieurs arguments», finir=' n * ')
impression('Prévention des sauts de ligne')
Il imprimerait le texte suivant:
L'impression en bref
* Appel de Print
* Séparer plusieurs arguments
* Prévenir les sauts de ligne
Comme vous pouvez le voir, le finir
L'argument mot-clé acceptera des chaînes arbitraires.
Noter: La boucle sur des lignes dans un fichier texte préserve leurs propres caractères de nouvelle ligne, qui, combinés avec le impression()
Le comportement par défaut de la fonction entraînera un caractère de nouvelle ligne redondant:
>>> avec ouvert("file.txt") comme objet_fichier:
... pour ligne dans objet_fichier:
... impression(ligne)
...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt 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 retours à la ligne après chaque ligne de texte. Vous souhaitez supprimer l'un d'entre eux, comme indiqué plus haut dans cet article, avant d'imprimer la ligne:
Vous pouvez également conserver la nouvelle ligne dans le contenu mais supprimer celle ajoutée par impression()
automatiquement. Vous utiliseriez le finir
argument de mot-clé pour faire cela:
>>> avec ouvert("file.txt") comme objet_fichier:
... pour ligne dans objet_fichier:
... impression(ligne, finir='')
...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt 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 par une chaîne vide, vous désactivez effectivement l'une des nouvelles lignes.
Vous vous familiarisez avec l’impression en Python, mais il reste encore beaucoup d’informations utiles à venir. Dans la sous-section à venir, vous apprendrez comment intercepter et rediriger le impression()
sortie de la fonction.
Pour empêcher un saut de ligne dans Python 2, vous devez ajouter une virgule de fin à l'expression:
Cependant, ce n’est pas idéal, car cela ajoute également 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 QUE'
impression 'Bonjour',
impression 'APRÈS'
Remarquez 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 l’importation du impression()
fonction de __avenir__
ou retomber au sys
module:
importer sys
impression 'AVANT QUE'
sys.stdout.écrivez('Bonjour')
impression 'APRÈS'
Cela imprimera la sortie correcte sans espace supplémentaire:
Lors de l'utilisation du 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 transformer les messages en texte sur votre écran, et franchement, il n’en a pas besoin. 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 semblable à un fichier. Un flux peut être n'importe quel fichier sur votre disque, une 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 est ce que vous voyez dans le terminal lorsque vous exécutez divers programmes de ligne de commande, y compris vos propres scripts Python:
$ chat bonjour.py
print ('Cela apparaîtra sur stdout')
$ python bonjour.py
Cela apparaîtra sur stdout
Sauf indication contraire, impression()
sera par défaut d'écrire sur la sortie standard. Cependant, vous pouvez demander à votre système d'exploitation de changer temporairement stdout
pour un flux de fichiers, de sorte que toute sortie aboutisse dans ce fichier plutôt que dans l'écran:
$ python hello.py> fichier.txt
$ cat file.txt
Cela apparaîtra sur stdout
C'est ce qu'on appelle la redirection de flux.
L'erreur standard est similaire à stdout
en ce qu 'il apparaît également à l'écran. Néanmoins, il s’agit d’un flux distinct, dont le but est de consigner les messages d’erreur à des fins de diagnostic. En redirigeant l'un d'entre eux ou les deux, vous pouvez garder les choses propres.
Noter: Rediriger stderr
, vous devez savoir descripteurs de fichiers, aussi connu sous le nom poignées de fichier.
Ce sont des nombres arbitraires, quoique constants, associés aux flux standard. Vous trouverez ci-dessous un résumé des descripteurs de fichiers pour une famille de systèmes d'exploitation compatibles POSIX:
Flux | Descripteur de fichier |
---|---|
stdin |
0 |
stdout |
1 |
stderr |
2 |
Connaître ces descripteurs vous permet de rediriger un ou plusieurs flux à la fois:
Commander | Description |
---|---|
./program> out.txt |
Réorienter stdout |
./programme 2> err.txt |
Réorienter stderr |
./program> out.txt 2> err.txt |
Réorienter stdout et stderr pour 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 tout comme les deux autres, vous pouvez échanger stdin
pour un fichier à partir duquel lire les données.
En Python, vous pouvez accéder à tous les flux standard via le sys
module:
>>> importer 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 voir, ces valeurs prédéfinies ressemblent à des objets de type fichier avec mode
et codage
attributs ainsi que .lire()
et .écrivez()
méthodes parmi tant d’autres.
Par défaut, impression()
est lié à sys.stdout
à travers son déposer
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 accèdent directement:
avec ouvert("file.txt", mode=«w») comme objet_fichier:
impression('Bonjour le monde', déposer=objet_fichier)
Cela rendra votre code immunisé contre la redirection de flux au niveau du système d'exploitation, ce qui pourrait être souhaité ou non.
Pour plus d'informations sur l'utilisation des fichiers en Python, vous pouvez consulter Lire et écrire des fichiers en Python (Guide).
Noter: N'essayez pas d'utiliser impression()
pour écrire des données binaires car il ne convient que pour le texte.
Appelez simplement le fichier binaire .écrivez()
directement:
avec ouvert('file.dat', «wb») comme objet_fichier:
objet_fichier.écrivez(octets(4))
objet_fichier.écrivez(b' xff')
Si vous vouliez écrire des octets bruts sur la sortie standard, cela échouera également car sys.stdout
est un flux de caractères:
>>> importer sys
>>> sys.stdout.écrivez(octets(4))
Traceback (dernier appel le plus récent):
Déposer "" , ligne 1, dans
Erreur-type: L'argument write () doit être str et non octets
Vous devez creuser plus profondément pour obtenir une poignée du flux d'octets sous-jacent à la place:
>>> importer sys
>>> num_bytes_written = sys.stdout.amortir.écrivez(b' x41 x0a')
UNE
Cela imprime une lettre majuscule UNE
et un caractère de nouvelle ligne, qui correspondent aux valeurs décimales de 65 et 10 en ASCII. Cependant, ils sont codés à l'aide de la notation hexadécimale dans le littéral d'octets.
Notez que impression()
n'a aucun contrôle sur le codage des caractères. Il est de la responsabilité du flux d’encoder correctement les chaînes Unicode reçues en octets. Dans la plupart des cas, vous ne définissez pas l'encodage vous-même, car l'UTF-8 par défaut est ce que vous voulez. Si vous en avez vraiment besoin, peut-être pour les systèmes hérités, vous pouvez utiliser le codage
argument de ouvert()
:
avec ouvert("file.txt", mode=«w», codage=«iso-8859-1») comme objet_fichier:
impression(«über café naïf», déposer=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:
>>> importer io
>>> fake_file = io.StringIO()
>>> impression('hello world', déposer=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 ouvert('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 ouvert('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 encoding
parameter, which would often result in the dreadful UnicodeEncodeError
:
>>> avec ouvert('file.txt', mode='w') comme file_object:
... unicode_text = u'xfcber naxefve cafxe9'
... impression >> file_object, unicode_text
...
Traceback (most recent call last):
Déposer "" , 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. Take a look at this example:
unicode_literal = u'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 = u'ü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 ouvert('file.txt', mode='w') comme file_object:
unicode_text = u'xfcber naxefve cafxe9'
encoded_text = unicode_text.encode('utf-8')
impression >> file_object, encoded_text
However, a more convenient option is to use the built-in codecs
module:
importer codecs
avec codecs.ouvert('file.txt', 'w', encoding='utf-8') comme file_object:
unicode_text = u'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:
importer temps
num_seconds = 3
pour countdown dans renversé(range(num_seconds + 1)):
si countdown > 0:
impression(countdown, finir='...')
temps.dormir(1)
autre:
impression('Go!')
As long as the countdown
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 Aller!
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(countdown, finir='...', 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:
importer temps
importer sys
num_seconds = 3
pour countdown dans renversé(range(num_seconds + 1)):
si countdown > 0:
sys.stdout.écrivez('%s...' % countdown)
sys.stdout.affleurer()
temps.dormir(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__ importer print_function
>>> aider(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 de la print()
fonction. You can display docstrings of various objects in Python using the built-in help()
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 importer 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. Take a look at this example:
classer La personne:
def __init__(soi, Nom, âge):
soi.Nom, soi.âge = 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 importer namedtuple
classer La personne(namedtuple('Person', 'name age')):
passe
Ton La personne
class has just become a specialized kind of namedtuple
with two attributes, which you can customize.
Note: In Python 3, the passe
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.
Note: 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 importer dataclass
>>> @dataclass
... classer La personne:
... 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)"
>>> taper(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.
Note: 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:
classer Utilisateur:
def __init__(soi, login, password):
soi.login = login
soi.password = password
def __str__(soi):
return soi.login
def __repr__(soi):
return F"User('soi.login', 'soi.password')"
If you print a single object of the Utilisateur
class, then you won’t see the password, because print(user)
will call 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:
classer Utilisateur(object):
def __init__(soi, login, password):
soi.login = login
soi.password = password
def __unicode__(soi):
return soi.login
def __str__(soi):
return unicode(soi).encode('utf-8')
def __repr__(soi):
utilisateur = u"User('%s', '%s')" % (soi.login, soi.password)
return utilisateur.encode('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(u'u043du0438u043au0438u0442u0430', u'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(u'u043du0438u043au0438u0442u0430', u'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:
>>> classer Utilisateur(object):
... def __init__(soi, login, password):
... soi.login = login
... soi.password = password
...
... def __bytes__(soi): # Python 3
... return soi.login.encode('utf-8')
...
>>> utilisateur = Utilisateur(u'u043du0438u043au0438u0442u0430', u'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 Quel 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:
>>> importer builtins
>>> builtins.impression
This way, you can avoid name collisions with custom functions. Let’s say you wanted to redefine 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()
:
>>> importer builtins
>>> println = builtins.impression
>>> def impression(*args, **kwargs):
... builtins.impression(*args, **kwargs, finir='')
...
>>> println('hello')
Bonjour
>>> impression('hellon')
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
:
>>> value = impression('hello world')
hello world
>>> impression(value)
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.
Parce que 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 composability. 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, log=impression):
log(F'Downloading URL')
# ...
def custom_print(*args):
passe # Do not print anything
Télécharger('/js/app.js', log=custom_print)
Here, the log
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.
Note: 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 pull fashion.
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. (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 importer partiel
>>> importer sys
>>> redirect = lambda fonction, flux: partiel(fonction, déposer=flux)
>>> prefix = lambda fonction, prefix: partiel(fonction, prefix)
>>> Erreur = prefix(redirect(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.
Note: 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, utilisateur.')
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.
impression
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
- assertion:
assert
Note: 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'
Déposer "" , line 1
lambda: impression 'hello world'
^
SyntaxError: invalid syntax
The syntax of the impression
statement is ambiguous. Sometimes you can add parentheses around the message, and they’re completely optional:
>>> impression 'Please wait...'
Please wait...
>>> impression('Please wait...')
Please wait...
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 ' '.rejoindre(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:
>>> aider(impression)
Déposer "" , line 1
aider(impression)
^
SyntaxError: invalid syntax
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.
Note: 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:
>>> importer __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__ importer 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__ importer print_function
>>> importer 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()
fonction.
Note: 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 la magie 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 importer 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 importer 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 range(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:
>>> items = [[[[1, 2, 3]
>>> items.append(items)
>>> impression(items)
[123[123[123[123[...]]
Pourtant, pprint()
is more explicit about it by including the unique identity of a self-referencing object:
>>> pp(items)
[123[123[123[123]
>>> identifiant(items)
140635757287688
The last element in the list is the same object as the entire list.
Note: Recursive or very large data sets can be dealt with using the reprlib
module as well:
>>> importer reprlib
>>> reprlib.repr([[[[X**dix pour X dans range(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:
>>> importer json
>>> Les données = 'username': 'jdoe', 'password': 's3cret'
>>> ugly = json.dumps(Les données)
>>> pretty = json.dumps(Les données, indent=4, sort_keys=Vrai)
>>> impression(ugly)
"username": "jdoe", "password": "s3cret"
>>> impression(pretty)
"password": "s3cret",
"username": "jdoe"
Notice, however, that you need to handle printing yourself, because it’s not something you’d typically want to do. De même, le 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 | Description | Exemple |
---|---|---|
Esc | non-printable escape character |
|