184 votes

Comment utiliser la nouvelle ligne ' \n ' dans f-string pour formater la sortie en Python 3.6 ?

J'aimerais savoir comment formater ce cas de manière pythonique avec des chaînes f :

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

Le problème est que '\' ne peut pas être utilisé à l'intérieur de la {...} des portions d'expression d'une chaîne f. Sortie attendue :

Winners are:
Adam
Bob
Cyril

18 votes

f"Winners are:\n{chr(10).join(names)}"

201voto

Jim Points 8793

Vous ne pouvez pas. Les barres obliques inverses ne peuvent pas apparaître à l'intérieur des accolades. {} ; ce faisant, il en résulte une SyntaxError :

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

Ceci est spécifié dans le PEP pour les cordes F :

Les barres obliques inverses ne peuvent pas apparaître à l'intérieur des portions d'expression des chaînes f, [...].

L'une des options est l'assinging '\n' à un nom et ensuite .join sur cela à l'intérieur de la f c'est-à-dire sans utiliser de littéral :

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

Résultats dans :

Winners are:
Adam
Bob
Cyril

Une autre option, comme spécifié par @wim, est d'utiliser chr(10) pour obtenir \n retourné et s'y joindre. f"Winners are:\n{chr(10).join(names)}"

Une autre encore, bien sûr, est de '\n'.join au préalable, puis ajoutez le nom en conséquence :

n = "\n".join(names)
text = f"Winners are:\n{n}"

ce qui donne le même résultat.

Note :

C'est l'une des petites différences entre f -stringues et str.format . Dans ce dernier cas, vous pouvez toujours utiliser la ponctuation en garantissant qu'un dict wacky correspondant contenant ces clés est déballé :

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(S'il vous plaît, ne faites pas ça.)

Dans le premier cas, la ponctuation n'est pas autorisée parce que vous ne pouvez pas avoir d'identifiants qui les utilisent.


A part ça : j'opterais définitivement pour print ou format comme le suggèrent les autres réponses comme alternative. Les options que j'ai données ne s'appliquent que si vous doit pour une raison quelconque, utilisent des chaînes en F.

Ce n'est pas parce que quelque chose est nouveau que vous devez essayer de tout faire avec ;-)

0 votes

Cela n'a pas de sens pour moi : nl = '\n' text = f"Winners are:{nl}" . Utilisation : texte = f "Les gagnants sont : \n "

0 votes

@Timo OP avait besoin de join sur \n dans une chaîne de format, en particulier dans l'expression incorporée.

70voto

eugene y Points 37378

Vous n'avez pas besoin de f-strings ou d'autres formateurs pour imprimer une liste de chaînes de caractères avec un séparateur. Il suffit de passer le sep argument de mot-clé à print() :

names = ['Adam', 'Bob', 'Cyril']
print("Winners are:", *names, sep="\n")

Sortie :

Winners are:
Adam
Bob
Cyril

Cela dit, l'utilisation str.format() ici serait sans doute plus simple et plus lisible que n'importe quelle solution de contournement de type f-string :

print("Winners are:\n{}".format("\n".join(names))

14 votes

La meilleure réponse jusqu'à présent. Ces jours-ci, j'utilise tout le temps le déballage en étoile dans la fonction d'impression pour jeter un coup d'œil à l'intérieur d'un objet, par exemple. print(*dir(some_object), sep='\n') ou print(*vars(some_object), sep='\n') .

2 votes

Que faire si l'on ne veut pas imprimer la liste directement, par exemple si on la transmet à un enregistreur ?

1 votes

@bob : alors utilisez simplement str.join() : text = '\n'.join(['Winners are:', *names]) . BTW, print() peut être utilisé pour écrire dans tout fichier (spécifié avec l'option file argument, sys.stdout par défaut).

20voto

Chris_Rands Points 15161

Comme d'autres l'ont dit, il n'est pas possible d'utiliser des antislashes dans les chaînes f, mais on peut contourner ce problème en utilisant os.linesep (mais notez que ce ne sera pas \n sur toutes les plateformes, et n'est pas recommandé à moins de lire/écrire des fichiers binaires ; voir Rick's commentaires) :

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

Ou peut-être d'une manière moins lisible, mais garantie pour être \n avec chr() :

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

2 votes

Ce n'était pas moi, mais en utilisant os.linesep est pas une bonne idée lors de la rédaction du texte.

1 votes

@RickTeachey J'ai déjà ajouté la mise en garde entre parenthèses et suggéré une autre approche. De toute façon, l'OP imprime à l'écran, et n'écrit pas dans un fichier ouvert en mode texte.

0 votes

Je ne pense pas que cela soit important. os.linesep est juste pour la lecture, ou la lecture et l'écriture en mode binaire . Je sais que cela fonctionnera de la même manière dans ce cas, mais c'est une mauvaise habitude à prendre. Mais encore une fois : Je n'étais pas le downvote. L'avertissement est suffisant pour moi :)

10voto

Rick Teachey Points 460

Les autres réponses donnent des idées sur la façon de placer le caractère de nouvelle ligne dans un champ f-string. Cependant, je dirais que pour l'exemple donné par le PO (qui peut ou non être indicatif du cas d'utilisation réel du PO), aucune de ces idées ne devrait être utilisée.

L'objectif de l'utilisation des chaînes f-strings est d'améliorer la lisibilité du code. Il n'y a rien que vous puissiez faire avec les chaînes f que vous ne pouvez pas faire avec format . Examinez attentivement s'il y a quelque chose plus lisible à ce sujet (si vous pouvez le faire) :

f"Winners are:\n{'\n'.join(names)}"

...ou ceci :

newline = '\n'
f"Winners are:\n{newline.join(names)}"

...ou ceci :

"Winners are:\n{chr(10).join(names)}"

contre ceci :

"Winners are:\n{}".format('\n'.join(names))

La dernière façon est au moins aussi lisible, sinon plus.

En bref : n'utilisez pas un marteau quand vous avez besoin d'un tournevis, juste parce que vous en avez un tout nouveau. Le code est lu bien plus souvent qu'il n'est écrit.

Pour d'autres cas d'utilisation, oui, il est possible que la chr(10) idée ou newline peut être approprié. Mais pas pour celle qui est donnée.

11 votes

La lisibilité est subjective :) ... les anciennes pratiques conviennent aux personnes expérimentées et peuvent être plus lisibles dans certains cas, mais peuvent être presque inconnues des novices et donc illisibles pour eux. Désolé pour ce point de vue philosophique.

2 votes

@malmed La lisibilité n'est généralement pas subjective. Certainement pas dans ce cas. Mais cela ne vaut pas la peine d'en débattre longuement.

1 votes

@malmed Vous avez raison de dire que la lisibilité est "subjective" dans le sens où elle est formable par une expérience antérieure. Mais comme notre cerveau et nos sens ont des limites, la lisibilité peut être mesurée objectivement en fonction de la facilité physique avec laquelle on peut parcourir le texte en question, de la fréquence à laquelle le cerveau humain a tendance à l'assimiler correctement, de la justesse des prédictions de notre cerveau concernant d'autres codes (y compris le début d'une déclaration ou d'une ligne qui laisse entrevoir la fin) et de la facilité avec laquelle un novice peut le lire.

3voto

CrackerKSR Points 444
print(f'{"blah\n"}')

La déclaration ci-dessus soulève SyntaxError , Mais pour éviter l'erreur, vous pouvez simplement assigner la chaîne contenant \n à une variable et l'utiliser dans f-string.

x = "blah\n"
print(f'{x}')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X